<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue + Cesium WebSocket实时轨迹播放</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.132/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <style>
        body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
        #app { width: 100%; height: 100vh; }
        #cesiumContainer { width: 100%; height: 100vh; }
        .info {
            position: absolute; top: 10px; left: 10px; z-index: 1000;
            background: rgba(0,0,0,0.8); color: #fff; padding: 14px; border-radius: 6px; max-width: 520px;
        }
        .row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
        .row button { background: #4CAF50; color: #fff; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; }
        .row button:hover { background: #45a049; }
        .row button.danger { background: #e84c3d; }
        .row button.danger:hover { background: #cf3e30; }
        .row button:disabled { background: #666; cursor: not-allowed; }
        .row select, .row input { padding: 4px 6px; font-size: 12px; }
        .kv { font-size: 12px; line-height: 1.6; }
        .kv b { color: #ffd666; }
        
        .env-selector {
            margin: 0;
            padding: 8px;
            background: rgba(0, 0, 0, 0.8);
            border-radius: 6px;
            border: 1px solid #444;
            display: flex;
            align-items: center;
            justify-content: space-between;
            min-width: 450px;
        }
        
        .env-selector .env-label {
            display: flex;
            align-items: center;
        }
        
        .env-selector .panel-controls {
            display: flex;
            align-items: center;
            gap: 5px;
        }
        

        
        .env-selector label {
            color: #fff;
            font-size: 12px;
            font-weight: bold;
        }
        
        .env-selector select {
            margin-left: 8px;
            padding: 4px 8px;
            background: #333;
            color: #fff;
            border: 1px solid #666;
            border-radius: 3px;
            font-size: 12px;
        }
        
        .env-selector select:focus {
            outline: none;
            border-color: #4CAF50;
        }
        
        /* SVG样式修改 */
        svg {
            background-color: #2c3e50 !important; /* 深蓝灰色背景 */
            font-family: 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', Arial, sans-serif !important; /* 中文字体优先 */
            font-size: 14px !important; /* 字体大小 */
            font-weight: 500 !important; /* 字体粗细 */
        }
        
        /* Cesium SVG按钮样式 */
        .cesium-button svg,
        .cesium-toolbar-button svg,
        .cesium-animation-rectButton svg {
            background-color: #34495e !important; /* 按钮背景色 */
            border-radius: 4px !important; /* 圆角 */
            padding: 2px !important; /* 内边距 */
        }
        
        /* SVG文本样式 */
        svg text,
        svg tspan {
            fill: #ecf0f1 !important; /* 文字颜色 */
            font-family: 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', Arial, sans-serif !important;
            font-size: 12px !important;
            font-weight: 400 !important;
        }
        
        /* SVG路径样式 */
        svg path {
            stroke: #3498db !important; /* 路径描边颜色 */
            stroke-width: 2px !important; /* 描边宽度 */
        }
        
        /* SVG圆形样式 */
        svg circle {
            fill: #e74c3c !important; /* 圆形填充颜色 */
            stroke: #c0392b !important; /* 圆形描边颜色 */
        }
        
        /* SVG矩形样式 */
        svg rect {
            fill: #9b59b6 !important; /* 矩形填充颜色 */
            stroke: #8e44ad !important; /* 矩形描边颜色 */
        }
        
        /* Cesium特定SVG样式 */
        .cesium-animation-svgText {
            background-color: #2c3e50 !important;
            font-family: 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', Arial, sans-serif !important;
        }
        
        .cesium-animation-svgText text {
            fill: #ecf0f1 !important;
            font-size: 14px !important;
            font-weight: 500 !important;
        }
        
        /* 导航帮助SVG样式 */
        .cesium-navigation-help svg {
            background-color: #34495e !important;
            border-radius: 6px !important;
        }
        
        .cesium-navigation-help svg text {
            fill: #ecf0f1 !important;
            font-size: 11px !important;
        }
        
        /* 信息框SVG样式 */
        .cesium-infoBox svg {
            background-color: #2c3e50 !important;
        }
        
        /* 时间轴SVG样式 */
        .cesium-timeline svg {
            background-color: #34495e !important;
        }
        
        .cesium-timeline svg text {
            fill: #ecf0f1 !important;
            font-size: 12px !important;
        }
        
        /* 场景模式选择器SVG样式 */
        .cesium-sceneModePicker svg {
            background-color: #34495e !important;
            border-radius: 4px !important;
        }
        
        /* 投影选择器SVG样式 */
        .cesium-projectionPicker svg {
            background-color: #34495e !important;
            border-radius: 4px !important;
        }
        
        /* SVG悬停效果 */
        svg:hover {
            background-color: #3d566e !important;
            transition: background-color 0.3s ease !important;
        }
        
        /* SVG动画效果 */
        svg {
            transition: all 0.3s ease !important;
        }
        
        /* SVG按钮悬停效果 */
        .cesium-button svg:hover,
        .cesium-toolbar-button svg:hover {
            background-color: #4a6b8a !important;
            transform: scale(1.05) !important;
        }
        
        /* SVG文本悬停效果 */
        svg text:hover,
        svg tspan:hover {
            fill: #f39c12 !important;
            transition: fill 0.3s ease !important;
        }
        
        /* SVG路径悬停效果 */
        svg path:hover {
            stroke: #e74c3c !important;
            stroke-width: 3px !important;
            transition: all 0.3s ease !important;
        }
        
        /* 导调下拉框选中状态样式 */
        .dropdown-item.selected {
            background-color: #f44336 !important;
            color: white !important;
        }
        
        .dropdown-item:hover {
            background-color: #555 !important;
        }
        .timeline { display:flex; align-items:center; gap:8px; margin-top:6px; }
        .timeline input[type="range"] { width: 240px; }
        
        /* 左侧面板样式 */
        .left-panel {
            position: absolute; top: 60px; left: 10px; z-index: 1000;
            background: rgba(0,0,0,0.8); color: #fff; padding: 14px; border-radius: 6px;
            max-width: 520px;
            transition: transform 0.3s ease, opacity 0.3s ease;
        }
        
        .left-panel.hidden {
            transform: translateX(-100%);
            opacity: 0;
        }
        
        /* 隐藏不需要的功能按钮，保留代码逻辑 */
        .left-panel .building-buttons {
            display: none;
        }
        
        /* 隐藏性能、相机、轨迹、白膜等控制功能 */
        .left-panel .performance-controls {
            display: none;
        }
        
        .left-panel .camera-controls {
            display: none;
        }
        
        .left-panel .track-controls {
            display: none;
        }
        
        .left-panel .white-mask-controls {
            display: none;
        }
        
        /* 隐藏状态信息 */
        .left-panel .status-info {
            display: none;
        }
        
        /* 隐藏统计按钮 */
        .left-panel .stats-buttons {
            display: none;
        }
        

        
        /* 右侧面板样式 */
        .right-panel {
            position: absolute; top: 10px; right: 10px; z-index: 1000;
            width: 600px; /* 移除最大高度和滚动条 */
            transition: transform 0.3s ease, opacity 0.3s ease;
            padding: 10px;
        }
        
        .right-panel.hidden {
            transform: translateX(100%);
            opacity: 0;
        }
        

        
        /* 任务列表表格样式 */
        .task-table {
            background: rgba(0,0,0,0.9); color: #fff; padding: 10px; border-radius: 6px;
            margin-bottom: 15px;
            max-height: 250px; /* 减小高度 */
            overflow-y: auto; /* 添加垂直滚动条 */
            display: none; /* 隐藏任务列表 */
        }
        
        /* 分页控制样式 */
        .pagination-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-top: 8px;
            padding: 6px 0;
            border-top: 1px solid #333;
        }
        
        .pagination-info {
            font-size: 11px;
            color: #ccc;
        }
        
        .pagination-buttons {
            display: flex;
            gap: 5px;
        }
        
        .pagination-btn {
            padding: 4px 8px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 11px;
        }
        
        .pagination-btn:disabled {
            background: #666;
            cursor: not-allowed;
        }
        
        .pagination-btn:hover:not(:disabled) {
            background: #45a049;
        }
        
        .page-size-selector {
            display: flex;
            align-items: center;
            gap: 5px;
        }
        
        .page-size-selector select {
            padding: 2px 4px;
            background: #333;
            color: #fff;
            border: 1px solid #666;
            border-radius: 2px;
            font-size: 11px;
        }
        .task-table h3 { margin: 0 0 8px 0; color: #ffd666; font-size: 14px; }
        .task-table table { width: 100%; border-collapse: collapse; font-size: 11px; table-layout: fixed; }
                 .task-table th, .task-table td { 
             padding: 4px 6px; text-align: left; border-bottom: 1px solid #333; 
         }
         
         .task-table td { 
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
         }
         
         .task-table th { 
             overflow: visible; white-space: nowrap; word-wrap: normal;
         }
                 .task-table th:nth-child(1), .task-table td:nth-child(1) { width: 18%; } /* 任务名称 */
         .task-table th:nth-child(2), .task-table td:nth-child(2) { width: 12%; } /* 开始时间 */
         .task-table th:nth-child(3), .task-table td:nth-child(3) { width: 12%; } /* 预计完成时间 */
         .task-table th:nth-child(4), .task-table td:nth-child(4) { width: 20%; } /* 起点 */
         .task-table th:nth-child(5), .task-table td:nth-child(5) { width: 20%; } /* 终点 */
         .task-table th:nth-child(6), .task-table td:nth-child(6) { width: 10%; } /* 预计里程 */
         .task-table th:nth-child(7), .task-table td:nth-child(7) { width: 8%; } /* 预计时长 */
        .task-table th { background: rgba(255,255,255,0.1); font-weight: bold; }
                 .task-table tr:hover { background: rgba(255,255,255,0.05); }
         
         .selected-task {
             background: rgba(255, 0, 0, 0.3) !important;
             border-left: 3px solid #ff0000;
         }
         
         .selected-task:hover {
             background: rgba(255, 0, 0, 0.4) !important;
         }
        .task-table .completed-task { 
            opacity: 0.6; 
            background: rgba(76, 175, 80, 0.1); 
        }
        
        /* 无任务数据样式 */
        .no-tasks {
            background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;
            text-align: center;
        }
        .no-tasks p {
            margin: 0; color: #999; font-size: 12px;
        }
        
        /* 轨迹属性面板样式 */
        .track-properties-panel {
            background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;
            margin-top: 10px;
            margin-bottom: 10px;
        }
        

        .track-properties-header {
            display: flex; justify-content: space-between; align-items: center;
            margin-bottom: 12px;
        }
        .track-properties-header h3 {
            margin: 0; color: #ffd666; font-size: 14px;
        }
        .track-selector {
            background: rgba(255,255,255,0.1); color: #fff; border: 1px solid #333;
            padding: 4px 8px; border-radius: 3px; font-size: 11px;
            min-width: 150px;
        }
        .track-selector option {
            background: #333; color: #fff;
        }
        .track-properties-content {
            font-size: 11px;
        }
        .property-group {
            margin-bottom: 12px;
        }
        .property-group h4 {
            margin: 0 0 6px 0; color: #4CAF50; font-size: 12px;
            border-bottom: 1px solid #333; padding-bottom: 2px;
        }
        .property-item {
            display: flex; justify-content: space-between; align-items: center;
            padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,0.1);
        }
        .property-label {
            color: #ccc; font-weight: bold; min-width: 80px;
        }
        .property-value {
            color: #fff; text-align: right; flex: 1;
        }
        .no-track-data, .no-track-selected {
            text-align: center; padding: 20px 0;
        }
        .no-track-data p, .no-track-selected p {
            margin: 0; color: #999; font-size: 12px;
        }
        
        /* 功能按钮组样式 */
        .function-buttons {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 10px;
            padding: 10px;
            background: rgba(255, 255, 255, 0.05);
            border-radius: 4px;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .function-buttons button {
            transition: all 0.3s ease;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        }
        
        .function-buttons button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
        }
        
                 .track-points-list {
             max-height: 300px;
             overflow-y: auto;
             border: 1px solid #444;
             border-radius: 4px;
             background: rgba(0, 0, 0, 0.3);
         }
         
         .track-point-header {
             display: flex;
             justify-content: space-between;
             align-items: center;
             padding: 8px 12px;
             background: rgba(255, 255, 255, 0.1);
             border-bottom: 2px solid #666;
             font-size: 12px;
             font-weight: bold;
             color: #fff;
             position: sticky;
             top: 0;
             z-index: 1;
         }
        
        .track-point-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 12px;
            border-bottom: 1px solid #333;
            font-size: 12px;
            line-height: 1.4;
        }
        
        .track-point-item:last-child {
            border-bottom: none;
        }
        
        .track-point-item:hover {
            background: rgba(255, 255, 255, 0.1);
        }
        
                 .point-index {
             flex: 0.5;
             color: #FFD700;
             font-weight: bold;
             text-align: center;
         }
         
         .point-time {
             flex: 1;
             color: #4CAF50;
             font-weight: bold;
         }
        
        .point-location {
            flex: 2;
            color: #2196F3;
        }
        
        .point-altitude {
            flex: 1;
            color: #FF9800;
            text-align: center;
        }
        
        .point-speed {
            flex: 1;
            color: #9C27B0;
            text-align: center;
        }
        
        .point-battery {
            flex: 1;
            color: #F44336;
            text-align: center;
        }
        
        /* GeoJSON表格样式 */
        .geojson-table {
            background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;
            max-height: 60vh; overflow-y: auto; margin-top: 10px;
        }
        .geojson-table h3 { margin: 0 0 12px 0; color: #ffd666; font-size: 14px; }
        .geojson-table table { width: 100%; border-collapse: collapse; font-size: 11px; }
        .geojson-table th, .geojson-table td { 
            padding: 6px 8px; text-align: left; border-bottom: 1px solid #333; 
        }
        .geojson-table th { background: rgba(255,255,255,0.1); font-weight: bold; }
        .geojson-table tr:hover { background: rgba(255,255,255,0.05); }
        .geojson-table .actions { display: flex; gap: 4px; }
        .geojson-table .actions button { 
            padding: 2px 6px; font-size: 10px; background: #2196F3; 
            border: none; color: white; border-radius: 3px; cursor: pointer; 
        }
        .geojson-table .actions button:hover { background: #1976D2; }
        .geojson-table .actions button.danger { background: #f44336; }
        .geojson-table .actions button.danger:hover { background: #d32f2f; }
        .geojson-table .json-preview { 
            max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 
        }
        
        /* 下拉菜单样式 */
        .dropdown {
            position: relative;
            display: inline-block;
        }
        
        .dropdown-toggle {
            background-color: #4CAF50 !important;
            color: white;
            border: none;
            cursor: pointer;
        }
        
        .dropdown-toggle:hover {
            background-color: #45a049 !important;
        }
        
        .dropdown-menu {
            display: none;
            position: absolute;
            background-color: #f9f9f9;
            min-width: 120px;
            box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
            z-index: 1000;
            border-radius: 4px;
            top: 100%;
            left: 0;
        }
        
        .dropdown:hover .dropdown-menu {
            display: block;
        }
        
        .dropdown-item {
            color: black;
            padding: 8px 12px;
            text-decoration: none;
            display: block;
            border: none;
            background: none;
            width: 100%;
            text-align: left;
            cursor: pointer;
            font-size: 12px;
        }
        
        .dropdown-item:hover {
            background-color: #f1f1f1;
        }
        
        /* 编辑对话框样式 */
        .edit-dialog-overlay {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.7); z-index: 2000; display: flex;
            align-items: center; justify-content: center;
        }
        
        .edit-dialog {
            background: #fff; border-radius: 8px; width: 80%; max-width: 800px;
            max-height: 80vh; overflow: hidden; display: flex; flex-direction: column;
        }
        
        .edit-dialog-header {
            background: #2196F3; color: white; padding: 15px 20px;
            display: flex; justify-content: space-between; align-items: center;
        }
        
        .edit-dialog-header h3 {
            margin: 0; font-size: 16px;
        }
        
        .close-btn {
            background: none; border: none; color: white; font-size: 24px;
            cursor: pointer; padding: 0; width: 30px; height: 30px;
            display: flex; align-items: center; justify-content: center;
        }
        
        .close-btn:hover {
            background: rgba(255,255,255,0.2); border-radius: 50%;
        }
        
        .edit-dialog-content {
            flex: 1; overflow-y: auto; padding: 20px;
        }
        
        .edit-table-container {
            max-height: 60vh; overflow-y: auto;
        }
        
        .edit-table {
            width: 100%; border-collapse: collapse; font-size: 12px;
        }
        
        .edit-table th, .edit-table td {
            padding: 8px 12px; text-align: left; border-bottom: 1px solid #ddd;
        }
        
        .edit-table th {
            background: #f5f5f5; font-weight: bold;
        }
        
        .edit-table tr:hover {
            background: #f9f9f9;
        }
        
        .edit-input {
            width: 100%; padding: 4px 8px; border: 1px solid #ddd;
            border-radius: 4px; font-size: 12px;
        }
        
        .edit-input:focus {
            outline: none; border-color: #2196F3;
        }
        
        .edit-dialog-footer {
            padding: 15px 20px; border-top: 1px solid #ddd;
            display: flex; gap: 10px; justify-content: flex-end;
        }
        
        .save-btn, .cancel-btn {
            padding: 8px 16px; border: none; border-radius: 4px;
            cursor: pointer; font-size: 12px;
        }
        
        .save-btn {
            background: #4CAF50; color: white;
        }
        
        .save-btn:hover {
            background: #45a049;
        }
        
        .cancel-btn {
            background: #f44336; color: white;
        }
        
        .cancel-btn:hover {
            background: #d32f2f;
        }
    </style>
</head>
<body>
<div id="app">
    <div id="cesiumContainer"></div>
    
    <!-- 环境选择器（始终显示） -->
    <div class="env-selector" style="position: absolute; top: 10px; left: 10px; z-index: 1001;">
        <div class="env-label">
            <label>环境：
                <select v-model="currentEnv" @change="onEnvChange">
                    <option value="dev">开发环境 (dev)</option>
                    <option value="test">测试环境 (test)</option>
                    <option value="prod">生产环境 (prod)</option>
                </select>
            </label>
        </div>
                    <div class="panel-controls">
                <span style="color: #fff; font-size: 11px; margin-right: 5px;">{{ leftPanelHidden ? '显示左侧面板' : '隐藏左侧面板' }}</span>
                <button @click="toggleLeftPanel" style="background: #FF5722; color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;" title="隐藏/显示左侧面板">
                    {{ leftPanelHidden ? '◀' : '▶' }}
                </button>


            </div>
    </div>
    
    <!-- 左侧面板 -->
    <div class="left-panel" :class="{ hidden: leftPanelHidden }">
        <div class="kv">状态：<b>{{ status }}</b></div>
        <div class="kv" style="display: flex; align-items: center; gap: 15px;">
            <span>WebSocket：<b :style="{color: isConnected ? '#4CAF50' : '#f44336'}">{{ isConnected ? '已连接' : '未连接' }}</b></span>
            <span>轨迹数量：<b>{{ flightTracks.length }}</b></span>
            <span>航线数量：<b>{{ routeCount }}</b></span>
            <span>初始坐标：<b>{{ initialLongitude.toFixed(6) }}, {{ initialLatitude.toFixed(6) }}</b></span>
        </div>
        <div class="row" style="display: flex; align-items: center; gap: 10px;">
            <label style="display: flex; align-items: center; margin: 0;">vid: <input v-model.number="vid" style="width: 60px; margin-left: 5px;" placeholder="660"></label>
            <label style="display: flex; align-items: center; margin: 0;">vidStatus: <input v-model.number="vidStatus" style="width: 60px; margin-left: 5px;" placeholder="2"></label>
            <button @click="sendSimulationMessage" :disabled="!isConnected" style="padding: 2px 6px; font-size: 10px; background: #9C27B0; color: white; border: none; border-radius: 3px; cursor: pointer;">仿真验证</button>
        </div>
        <div class="row">
            <label>WebSocket地址：
                <input v-model="websocketUrl" style="width: 200px;" placeholder="ws://127.0.0.1:6088/uam/v2/ws/uam/channel/245">
                <button v-if="!isConnected" @click="reconnectWebSocket">重连</button>
                <button v-else @click="disconnectWebSocket" style="background-color: #f44336;">断开</button>
            </label>
        </div>
        <div class="row">
            <label>获取航线：ClientType: <input v-model="wsClientType" style="width: 50px;" placeholder="1"> 方案Id: <input v-model="planId" style="width: 50px;" placeholder="1"> 需求Id: <input v-model="schemaRequirementId" style="width: 80px;" placeholder="798"> <button @click="sendInitMessage" :disabled="!isConnected">获取需求对应的航线</button> <button @click="updateBatchPlanIdFromInput" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer;">同步方案ID</button> <button @click="sendLandingFieldMessage" :disabled="!isConnected" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #FF9800; color: white; border: none; border-radius: 3px; cursor: pointer;">起降场</button> <button @click="sendTaskMessage" :disabled="!isConnected" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer;">获取任务</button></label>
        </div>
        <div class="row">
            <button @click="focusFirstPoint">定位到起点</button>
              <button @click="focusToInitialLocation">定位到初始位置</button>
              <button @click="resetToInitialLocation">重置位置</button>
                             <button @click="clearAllTracks" class="danger">清除所有轨迹</button>
                             <button @click="logPerformanceStats" class="stats-buttons" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #9C27B0; color: white; border: none; border-radius: 3px; cursor: pointer;">性能统计</button>
                             <button @click="resetTaskCompletionStats" class="stats-buttons" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #FF9800; color: white; border: none; border-radius: 3px; cursor: pointer;">重置统计</button>
               <button @click="clearHistoricalTracks" class="danger">清除历史轨迹</button>
               <button @click="clearAllRoutes" class="danger">清除所有航线</button>
               <button @click="clearAllLandingFields" class="danger">清除所有起降场</button>
               <button @click="toggleLandingFieldNames" :style="{background: showLandingFieldNames ? '#4CAF50' : '#FF9800', color: 'white', border: 'none', padding: '4px 8px', borderRadius: '3px', cursor: 'pointer', fontSize: '11px', marginLeft: '5px'}">
                   {{ showLandingFieldNames ? '隐藏起降场名称' : '显示起降场名称' }}
               </button>
                         <label class="performance-controls">渲染间隔：
                 <select v-model.number="renderDelay" @change="updateRenderDelay">
                     <option :value="500">0.5秒</option>
                     <option :value="1000">1秒</option>
                     <option :value="2000">2秒</option>
                     <option :value="5000">5秒</option>
                </select>
             </label>
             <label class="performance-controls">更新节流：
                 <select v-model.number="updateThrottle" @change="updateRenderDelay">
                     <option :value="200">0.2秒</option>
                     <option :value="500">0.5秒</option>
                     <option :value="1000">1秒</option>
                 </select>
             </label>
             <label class="performance-controls">实时更新：
                 <input type="checkbox" v-model="enableRealTimeUpdate" @change="toggleRealTimeUpdate">
             </label>
             <label class="performance-controls">性能优化：
                 <select v-model.number="performanceLevel" @change="updatePerformanceSettings">
                     <option :value="1">低性能 (流畅)</option>
                     <option :value="2">中性能 (平衡)</option>
                     <option :value="3">高性能 (详细)</option>
                 </select>
             </label>

             <label class="camera-controls">相机锁定：
                 <input type="checkbox" v-model="cameraLocked" @change="toggleCameraLock">
             </label>
             <button @click="lockCurrentZoomLevel" class="camera-controls" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer;">锁定当前级别</button>
             <button @click="unlockCamera" class="camera-controls" style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #f44336; color: white; border: none; border-radius: 3px; cursor: pointer;">解锁相机</button>
                           <label class="track-controls">历史轨迹：
                  <input type="checkbox" v-model="showHistoricalTracks" @change="toggleHistoricalTracks">
              </label>
              <label class="track-controls">分段颜色：
                  <input type="checkbox" v-model="enableSegmentedColors">
            </label>
        </div>

        
        <!-- 白膜效果控制 -->
        <div class="row white-mask-controls">
            <button @click="addWhiteMask" :disabled="whiteMask" class="btn">添加白膜</button>
            <button @click="removeWhiteMask" :disabled="!whiteMask" class="btn">移除白膜</button>
            <div v-if="whiteMask" style="margin-top: 5px;">
                <label style="font-size: 12px; margin-right: 5px;">透明度:</label>
                <input type="range" min="0" max="100" value="30" @input="adjustWhiteMaskOpacity($event.target.value / 100)" style="width: 80px;">
                <span style="font-size: 12px; margin-left: 5px;">{{ Math.round((whiteMaskOpacity || 0.3) * 100) }}%</span>
            </div>
        </div>
        
        <!-- 建筑物白膜效果控制 -->
        <div class="row building-buttons">
            <button @click="load3DBuildings" class="btn">加载3D建筑物</button>
            <button @click="createTestBuilding" class="btn">创建测试建筑物</button>
            <button @click="debug3DTiles" class="btn">调试3D图层</button>
            <button @click="addBuildingWhiteMask" :disabled="buildingMaskActive" class="btn">添加建筑物白膜</button>
            <button @click="removeBuildingWhiteMask" :disabled="!buildingMaskActive" class="btn">移除建筑物白膜</button>
            <div v-if="buildingMaskActive" style="margin-top: 5px;">
                <label style="font-size: 12px; margin-right: 5px;">透明度:</label>
                <input type="range" min="0" max="100" value="30" @input="adjustBuildingMaskOpacity($event.target.value / 100)" style="width: 80px;">
                <span style="font-size: 12px; margin-left: 5px;">{{ Math.round((buildingMaskOpacity || 0.3) * 100) }}%</span>
            </div>
        </div>
        
        <!-- 白膜3D Tiles控制 -->
        <div class="row">
            <button @click="testBaimoConnection" class="btn">测试白膜连接</button>
            <button @click="loadBaimoTileset" class="btn">加载白膜3D Tiles</button>
            <button @click="removeBaimoTileset" :disabled="!baimoTileset" class="btn danger">移除白膜3D Tiles</button>
            <button @click="toggleBaimoWhiteMask" :disabled="!baimoTileset" class="btn">{{ baimoWhiteMaskActive ? '禁用白膜效果' : '启用白膜效果' }}</button>
            <button @click="debugBaimoTileset" :disabled="!baimoTileset" class="btn">调试白膜</button>
            <button @click="forceLocateBaimo" :disabled="!baimoTileset" class="btn">强制定位</button>
            <div v-if="baimoTileset" style="margin-top: 5px;">
                <label style="font-size: 12px; margin-right: 5px;">透明度:</label>
                <input type="range" min="0" max="100" value="80" @input="adjustBaimoMaskOpacity($event.target.value / 100)" style="width: 80px;">
                <span style="font-size: 12px; margin-left: 5px;">{{ Math.round((baimoMaskOpacity || 0.8) * 100) }}%</span>
            </div>
        </div>
        
        <!-- 视角控制功能 -->
        <div class="row">
            <button @click="switchToTopView" class="btn">平面视图</button>
            <button @click="switchTo3DView" class="btn">3D视图</button>
            <button @click="switchToVerticalView" class="btn">垂直视图</button>
            <button @click="switchToNorthView" class="btn">北向视图</button>
            <button @click="showCurrentViewInfo" class="btn">视角信息</button>
        </div>
         


                 <div class="kv status-info">当前位置：<b>{{ posText }}</b></div>
         <div class="kv status-info">当前区段：<b>{{ segText }}</b></div>
         <div class="kv status-info">飞行方向：<b>{{ headingText }}</b></div>
         <div class="kv" style="display: flex; align-items: center; gap: 15px;">
             <div style="text-align: center;">
                 <div style="font-size: 11px; color: #ccc; margin-bottom: 2px;">地图缩放</div>
                 <div style="font-size: 12px; color: #fff; font-weight: bold;">{{ currentZoomLevelDisplay }}级</div>
             </div>
             <div style="text-align: center;">
                 <div style="font-size: 11px; color: #ccc; margin-bottom: 2px;">地图类型</div>
                 <div style="font-size: 12px; color: #fff; font-weight: bold;">{{ currentMapType }}</div>
             </div>
             <div style="text-align: center;">
                 <div style="font-size: 11px; color: #ccc; margin-bottom: 2px;">方案ID</div>
                 <div style="font-size: 12px; color: #fff; font-weight: bold;">{{ planId }}</div>
             </div>
             <div style="text-align: center;">
                 <div style="font-size: 11px; color: #ccc; margin-bottom: 2px;">轨迹统计</div>
                 <div style="font-size: 12px; color: #fff; font-weight: bold;">{{ trackStats }}</div>
             </div>
         </div>
         <div class="kv status-info">定位状态：<b :style="{color: initialLocationSet ? '#4CAF50' : '#ff9800'}">{{ initialLocationSet ? '已定位' : '定位中...' }}</b></div>
         
         <!-- 飞行器任务信息面板 -->
         <div v-if="selectedTrackId && selectedTaskInfo" class="aircraft-task-panel" style="margin-top: 20px; background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;">
             <div class="task-info-header">
                 <h3 style="margin: 0 0 12px 0; color: #ffd666; font-size: 14px;">飞行器任务信息（{{ selectedTrackId }}）</h3>
             </div>
             <div class="task-info-content">
                 <div class="property-group">
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">任务名称:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.name || '未知' }}</span>
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">开始时间:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ formatTaskTime(selectedTaskInfo.departureTime) || '未知' }}</span>
                     </div>
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">起点:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.origin || '未知' }}</span>
                     </div>
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">终点:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.destination || '未知' }}</span>
                     </div>
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">预计里程:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.mileage || 'N/A' }}</span>
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">预计时长:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.duration || 'N/A' }}</span>
                     </div>
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">航线模型:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.routeModel || 'N/A' }}</span>
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">任务类型:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.missionType || 'N/A' }}</span>
                     </div>
                     <div class="property-item" style="display: flex; justify-content: flex-start; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">飞行器类型:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">{{ selectedTaskInfo.aircraftType || '未知' }}</span>
                         <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">任务状态:</span>
                         <span class="property-value" style="color: #fff; text-align: left; flex: 1;">
                             <span v-if="taskStatus[selectedTaskInfo.uuid]?.completed" style="color: #4CAF50;">已完成</span>
                             <span v-else style="color: #FF9800;">进行中</span>
                         </span>
                     </div>
                 </div>
             </div>
         </div>
     </div>
     

     
     <!-- 导调信息面板（独立显示，不受右侧面板隐藏影响） -->
     <div class="geojson-panel" style="position: absolute; top: 10px; right: 10px; z-index: 1000; background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px; margin-bottom: 10px; width: 600px; max-height: 80vh; overflow-y: auto; transition: transform 0.3s ease, opacity 0.3s ease;">
             <!-- 顶部并排显示：标题、展开/收缩按钮和绘制按钮 -->
             <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px solid #333;">
                 <div style="display: flex; align-items: center; gap: 10px;">
                     <h3 style="margin: 0;">导调信息 ({{ geojsonRecords.length }})</h3>
                     <button @click="toggleGeojsonPanel" style="background: #FF9800; color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;" title="展开/收缩所有面板">
                         {{ geojsonPanelExpanded ? '收缩' : '展开' }}
                     </button>

                     <button @click="selectDispatchOption(flightTracks.find(t => t.id === selectedTrackId), 'return_home')" style="background: #FF9800; color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;" title="返航">
                          返航
                     </button>

                     <button @click="selectDispatchOption(flightTracks.find(t => t.id === selectedTrackId), 'forced_landing')" style="background: #FF9800; color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;" title="迫降">
                          迫降
                     </button>

                     <button @click="selectDispatchOption(flightTracks.find(t => t.id === selectedTrackId), 'crash')" style="background: #FF9800; color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;" title="坠毁">
                          坠毁
                     </button>

                 </div>
                 
                 <!-- 绘制多边形控制按钮 -->
                 <div style="display: flex; align-items: center; gap: 8px;">
                     <button @click="startDrawPolygon" :disabled="drawing" style="background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px;">
                         {{ drawing ? '绘制中...' : '开始绘制多边形' }}
                     </button>
                     <!-- <button @click="finishDrawPolygon" :disabled="!drawing" style="background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px;">
                         完成
                     </button> -->
                     <button @click="clearDrawPolygon" class="danger" style="background: #f44336; color: white; border: none; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px;">
                         清空多边形
                     </button>
                 </div>
             </div>
             
             <!-- 操作提示 -->
             <div v-if="geojsonPanelExpanded" style="margin-bottom: 15px; font-size: 11px; color: #ccc; text-align: center;">
                 提示：左键落点、移动预览、右键完成。地图滚动后不会自动重新定位。
             </div>
             
             <div v-if="geojsonPanelExpanded && geojsonRecords.length > 0" style="margin-bottom: 10px;">
                 <label>批量设置方案ID：
                     <input v-model.number="batchPlanId" 
                            type="number" 
                            min="1" 
                            style="width: 60px; padding: 2px; font-size: 12px;"
                            placeholder="1">
                     <button @click="setBatchPlanId" 
                             style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer;">
                         应用
                     </button>
                 </label>
                 <label style="margin-left: 20px;">批量设置名称前缀：
                     <input v-model="batchNamePrefix" 
                            type="text" 
                            style="width: 80px; padding: 2px; font-size: 12px;"
                            placeholder="导调区域">
                     <button @click="setBatchNames" 
                             style="margin-left: 5px; padding: 2px 6px; font-size: 10px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer;">
                         应用
                     </button>
                 </label>
             </div>
             <table v-if="geojsonPanelExpanded && geojsonRecords.length > 0" style="width: 100%; border-collapse: collapse; font-size: 12px;">
                 <thead>
                     <tr>
                         <th style="padding: 8px; text-align: left; border-bottom: 1px solid #333;">序号</th>
                         <th style="padding: 8px; text-align: left; border-bottom: 1px solid #333;">区域名称</th>
                         <th style="padding: 8px; text-align: left; border-bottom: 1px solid #333;">边界点数</th>
                         <th style="padding: 8px; text-align: left; border-bottom: 1px solid #333;">方案ID</th>
                         <th style="padding: 8px; text-align: left; border-bottom: 1px solid #333;">操作</th>
                     </tr>
                 </thead>
                 <tbody>
                     <tr v-for="(record, index) in geojsonRecords" :key="index">
                         <td style="padding: 8px; border-bottom: 1px solid #333;">{{ index + 1 }}</td>
                         <td style="padding: 8px; border-bottom: 1px solid #333;">
                             <input v-model="record.name" 
                                    type="text" 
                                    style="width: 80px; padding: 2px; font-size: 12px;"
                                    :placeholder="`导调区域${index + 1}`"
                                    title="区域名称">
                         </td>

                         <td style="padding: 8px; border-bottom: 1px solid #333;">{{ record.pointCount }}</td>
                         <td style="padding: 8px; border-bottom: 1px solid #333;">
                             <input v-model="record.planId" 
                                    type="number" 
                                    min="1" 
                                    style="width: 60px; padding: 2px; font-size: 12px;"
                                    placeholder="1"
                                    title="方案ID">
                         </td>
                         <td style="padding: 8px; border-bottom: 1px solid #333;" class="actions">
                             <button @click="copyRecordGeoJSON(index)" title="复制GeoJSON" style="padding: 2px 6px; font-size: 10px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; margin-right: 2px;">复制</button>
                             <button @click="viewRecordGeoJSON(index)" title="查看完整GeoJSON" style="padding: 2px 6px; font-size: 10px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; margin-right: 2px;">查看</button>
                             <button @click="deleteRecord(index)" class="danger" title="删除记录" style="padding: 2px 6px; font-size: 10px; background: #f44336; color: white; border: none; border-radius: 3px; cursor: pointer; margin-right: 2px;">删除</button>
                             <div class="dropdown" style="display: inline-block;">
                                 <button class="btn-small dropdown-toggle" style="padding: 2px 6px; font-size: 10px; background: #FF9800; color: white; border: none; border-radius: 3px; cursor: pointer;">导调</button>
                                 <div class="dropdown-menu" style="position: absolute; background: rgba(0,0,0,0.9); border: 1px solid #333; border-radius: 3px; padding: 5px; min-width: 120px;">
                                     <button @click="selectDispatchOption(record, 'local_avoidance')" 
                                             class="dropdown-item" 
                                             :class="{ 'selected': record.selectedDispatchOption === 'local_avoidance' }"
                                             style="display: block; width: 100%; padding: 4px 8px; background: none; color: white; border: none; text-align: left; cursor: pointer; font-size: 10px;">
                                         局部避障
                                     </button>
                                     <!-- <button @click="selectDispatchOption(record, 'forced_landing')" 
                                             class="dropdown-item" 
                                             :class="{ 'selected': record.selectedDispatchOption === 'forced_landing' }"
                                             style="display: block; width: 100%; padding: 4px 8px; background: none; color: white; border: none; text-align: left; cursor: pointer; font-size: 10px;">
                                         迫降
                                     </button>
                                     <button @click="selectDispatchOption(record, 'return_home')" 
                                             class="dropdown-item" 
                                             :class="{ 'selected': record.selectedDispatchOption === 'return_home' }"
                                             style="display: block; width: 100%; padding: 4px 8px; background: none; color: white; border: none; text-align: left; cursor: pointer; font-size: 10px;">
                                         返航
                                     </button>
                                     <button @click="selectDispatchOption(record, 'crash')" 
                                             class="dropdown-item" 
                                             :class="{ 'selected': record.selectedDispatchOption === 'crash' }"
                                             style="display: block; width: 100%; padding: 4px 8px; background: none; color: white; border: none; text-align: left; cursor: pointer; font-size: 10px;">
                                         坠毁
                                     </button> -->
                                 </div>
                             </div>
                         </td>
                     </tr>
                 </tbody>
             </table>
             <div v-if="geojsonPanelExpanded && geojsonRecords.length === 0" style="text-align: center; color: #999; padding: 20px;">
                 暂无导调区域
             </div>
             
             <!-- 任务列表面板 -->
             <div class="task-table" v-if="geojsonPanelExpanded && sortedTaskList.length > 0" style="margin-top: 20px; background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px; display: none;">
                 <h3 style="margin: 0 0 12px 0; color: #ffd666; font-size: 14px;">
                     任务列表 ({{ sortedTaskList.length }}) - 显示第{{ (currentTaskPage - 1) * taskPageSize + 1 }}-{{ Math.min(currentTaskPage * taskPageSize, sortedTaskList.length) }}条任务，共{{ sortedTaskList.length }}条
                 </h3>
                 <div style="max-height: 120px; overflow: hidden;">
                     <table style="width: 100%; border-collapse: collapse; font-size: 11px;">
                     <thead>
                         <tr>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">任务名称</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">开始时间</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">预计完成时间</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">起点</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">终点</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">预计里程</th>
                             <th style="padding: 6px; text-align: left; border-bottom: 1px solid #333; background: rgba(255,255,255,0.1);">预计时长</th>
                         </tr>
                     </thead>
                     <tbody>
                         <tr v-for="(task, index) in paginatedTaskList" :key="task.uuid" :class="{ 
                             'completed-task': taskStatus[task.uuid]?.completed,
                             'selected-task': isTaskSelected(task.uuid)
                         }" style="border-bottom: 1px solid #333;">
                             <td style="padding: 6px;">{{ task.name }}</td>
                             <td style="padding: 6px;">{{ formatTaskTime(task.departureTime) }}</td>
                             <td style="padding: 6px;">{{ formatTime(task.endTime) }}</td>
                             <td style="padding: 6px;">{{ task.origin }}</td>
                             <td style="padding: 6px;">{{ task.destination }}</td>
                             <td style="padding: 6px;">{{ task.mileage || 'N/A' }}</td>
                             <td style="padding: 6px;">{{ task.duration || 'N/A' }}</td>
                         </tr>
                     </tbody>
                     </table>
                 </div>
                 
                 <!-- 分页控件 -->
                 <div class="pagination-controls" style="margin-top: 12px; padding-top: 8px; border-top: 1px solid #333;">
                     <div class="pagination-buttons" style="display: flex; justify-content: center; align-items: center; gap: 8px;">
                         <button @click="goToFirstTaskPage" :disabled="currentTaskPage === 1" 
                                 style="padding: 4px 8px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;"
                                 :style="{ background: currentTaskPage === 1 ? '#666' : '#4CAF50', cursor: currentTaskPage === 1 ? 'not-allowed' : 'pointer' }">
                             首页
                         </button>
                         <button @click="goToPrevTaskPage" :disabled="currentTaskPage === 1" 
                                 style="padding: 4px 8px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;"
                                 :style="{ background: currentTaskPage === 1 ? '#666' : '#2196F3', cursor: currentTaskPage === 1 ? 'not-allowed' : 'pointer' }">
                             上一页
                         </button>
                         <span style="color: #fff; font-size: 11px; margin: 0 8px;">
                             第{{ currentTaskPage }}页 / 共{{ totalTaskPages }}页
                         </span>
                         <button @click="goToNextTaskPage" :disabled="currentTaskPage === totalTaskPages" 
                                 style="padding: 4px 8px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;"
                                 :style="{ background: currentTaskPage === totalTaskPages ? '#666' : '#2196F3', cursor: currentTaskPage === totalTaskPages ? 'not-allowed' : 'pointer' }">
                             下一页
                         </button>
                         <button @click="goToLastTaskPage" :disabled="currentTaskPage === totalTaskPages" 
                                 style="padding: 4px 8px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 10px;"
                                 :style="{ background: currentTaskPage === totalTaskPages ? '#666' : '#4CAF50', cursor: currentTaskPage === totalTaskPages ? 'not-allowed' : 'pointer' }">
                             末页
                         </button>
                         <select v-model="taskPageSize" @change="onTaskPageSizeChange" 
                                 style="padding: 4px 6px; background: #333; color: #fff; border: 1px solid #666; border-radius: 3px; font-size: 10px; margin-left: 8px;">
                             <option value="3">每页3条</option>
                             <option value="5">每页5条</option>
                             <option value="10">每页10条</option>
                             <option value="20">每页20条</option>
                         </select>
                     </div>
                 </div>
             </div>
             <div v-else-if="geojsonPanelExpanded && sortedTaskList.length === 0" class="no-tasks" style="margin-top: 20px; background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px; text-align: center;">
                 <p style="margin: 0; color: #999; font-size: 12px;">暂无任务数据</p>
             </div>
             
             <!-- 轨迹属性面板 -->
             <div class="track-properties-panel" v-if="geojsonPanelExpanded" style="margin-top: 20px; background: rgba(0,0,0,0.9); color: #fff; padding: 14px; border-radius: 6px;">
                 <div class="track-properties-header">
                     <h3 style="margin: 0 0 12px 0; color: #ffd666; font-size: 14px;">轨迹属性</h3>
                     <select v-model="selectedTrackId" @change="onTrackSelectionChange" class="track-selector" style="background: rgba(255,255,255,0.1); color: #fff; border: 1px solid #333; padding: 4px 8px; border-radius: 3px; font-size: 11px; min-width: 150px;">
                         <option value="">请选择轨迹</option>
                         <option v-for="track in flightTracks" :key="track.id" :value="track.id"
                                 :style="{color: track.id === selectedTrackId ? 'red' : 'cyan'}">
                             {{ getTaskNameByTrackId(track.id) }}
                         </option>
                     </select>
                     
                     <!-- 功能按钮组 - 只在选中轨迹时显示 -->
                     <div v-if="selectedTrackId && showFunctionButtons" class="function-buttons" style="margin-top: 10px;">
                         <button @click="startRealTimeMovement" style="margin-right: 8px; padding: 4px 8px; background: #FF9800; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             启动实时移动
                         </button>
                         <button @click="stopRealTimeMovement" style="margin-right: 8px; padding: 4px 8px; background: #f44336; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             停止实时移动
                         </button>
                         <button @click="trackAircraft(selectedTrackId)" style="margin-right: 8px; padding: 4px 8px; background: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             跟随视角
                         </button>
                         <button @click="startContinuousFollow(selectedTrackId)" style="margin-right: 8px; padding: 4px 8px; background: #00BCD4; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             持续跟随
                         </button>
                         <button @click="switchToFirstPersonView(selectedTrackId)" style="margin-right: 8px; padding: 4px 8px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             第一视角
                         </button>
                         <button @click="returnToDefaultMode" style="margin-right: 8px; padding: 4px 8px; background: #9E9E9E; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 11px;">
                             返回默认
                         </button>
                     </div>
                 </div>
                 
                 <div class="track-properties-content" v-if="selectedTrackId && selectedTrackData" style="margin-top: 15px;">
                     <div class="property-group" v-if="selectedTrackData">
                         <h4 style="margin: 0 0 8px 0; color: #4CAF50; font-size: 12px; border-bottom: 1px solid #333; padding-bottom: 4px;">
                             基本信息 - 时间: {{ getCurrentDate() }}
                         </h4>
                         <div class="property-item" style="display: flex; justify-content: space-between; align-items: center; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1);">
                             <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px;">飞行器类型:</span>
                             <span class="property-value" style="color: #fff; text-align: right; flex: 1;">{{ selectedTrackData.aircraft_type || '未知' }}</span>
                             <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">任务类型:</span>
                             <span class="property-value" style="color: #fff; text-align: right; flex: 1;">{{ selectedTrackData.mission_type || '未知' }}</span>
                             <span class="property-label" style="color: #ccc; font-weight: bold; min-width: 80px; margin-left: 20px;">轨迹点数:</span>
                             <span class="property-value" style="color: #fff; text-align: right; flex: 1;">{{ selectedTrackData.points ? selectedTrackData.points.length : 0 }}</span>
                         </div>
                     </div>
                     
                     <div class="property-group" v-if="recentTrackPoints && recentTrackPoints.length > 0" style="margin-top: 15px;">
                         <h4 style="margin: 0 0 8px 0; color: #4CAF50; font-size: 12px; border-bottom: 1px solid #333; padding-bottom: 4px;">轨迹点信息</h4>
                         <div class="track-points-list" style="max-height: 200px; overflow-y: auto; border: 1px solid #444; border-radius: 4px; background: rgba(0, 0, 0, 0.3);">
                             <div class="track-point-header" style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; background: rgba(255, 255, 255, 0.1); border-bottom: 2px solid #666; font-size: 11px; font-weight: bold; color: #fff; position: sticky; top: 0;">
                                 <span class="point-index" style="width: 40px;">序号</span>
                                 <span class="point-time" style="width: 80px;">时间</span>
                                 <span class="point-location" style="width: 120px;">位置</span>
                                 <span class="point-altitude" style="width: 60px;">高度</span>
                                 <span class="point-speed" style="width: 60px;">速度</span>
                                 <span class="point-battery" style="width: 60px;">电池</span>
                             </div>
                             <div class="track-point-item" v-for="(point, index) in recentTrackPoints" :key="index" style="display: flex; justify-content: space-between; align-items: center; padding: 4px 8px; border-bottom: 1px solid #333; font-size: 10px;">
                                 <span class="point-index" style="width: 40px;">{{ getPointIndex(point) }}</span>
                                 <span class="point-time" style="width: 80px;">{{ point.timestamp_absolute ? formatTimeOnly(point.timestamp_absolute) : 'N/A' }}</span>
                                 <span class="point-location" style="width: 120px;">{{ point.longitude ? point.longitude.toFixed(6) : 'N/A' }}, {{ point.latitude ? point.latitude.toFixed(6) : 'N/A' }}</span>
                                 <span class="point-altitude" style="width: 60px;">{{ point.altitude || 'N/A' }}</span>
                                 <span class="point-speed" style="width: 60px;">{{ point.speed || 'N/A' }}</span>
                                 <span class="point-battery" style="width: 60px;">{{ point.battery || 'N/A' }}</span>
                             </div>
                         </div>
                     </div>
                 </div>
                 
                 <div v-else-if="selectedTrackId" class="no-track-data" style="margin-top: 15px; text-align: center; padding: 20px 0;">
                     <p style="margin: 0; color: #999; font-size: 12px;">未找到轨迹数据</p>
                 </div>
                 <div v-else class="no-track-selected" style="margin-top: 15px; text-align: center; padding: 20px 0;">
                     <p style="margin: 0; color: #999; font-size: 12px;">请选择轨迹查看属性</p>
                 </div>
             </div>
         </div>
         
         <!-- 右侧面板 -->
         <div class="right-panel" :class="{ hidden: rightPanelHidden }" style="position: absolute; top: 500px; right: 10px; z-index: 1000; width: 600px;">
             <!-- 右侧面板现在为空，可以隐藏或移除 -->
         </div>
         
     
     <!-- GeoJSON记录面板 -->
     <!-- 编辑对话框 -->
     <div v-if="showEditDialogFlag" class="edit-dialog-overlay" @click="closeEditDialog">
         <div class="edit-dialog" @click.stop>
             <div class="edit-dialog-header">
                 <h3>{{ currentEditTitle }}</h3>
                 <button class="close-btn" @click="closeEditDialog">&times;</button>
             </div>
             <div class="edit-dialog-content">
                 <div class="edit-table-container">
                     <table class="edit-table">
                         <thead>
                             <tr>
                                 <th>属性名</th>
                                 <th>属性值</th>
                             </tr>
                         </thead>
                         <tbody>
                             <tr v-for="(value, key) in editedExtraAttributes" :key="key">
                                 <td>{{ key }}</td>
                                 <td>
                                     <input v-model="editedExtraAttributes[key]" 
                                            type="text" 
                                            class="edit-input"
                                            :placeholder="value">
                                 </td>
                             </tr>
                         </tbody>
                     </table>
                 </div>
             </div>
             <div class="edit-dialog-footer">
                 <button @click="saveEditDialog" class="save-btn">修改</button>
                 <button @click="closeEditDialog" class="cancel-btn">取消</button>
             </div>
         </div>
     </div>
</div>

<script>
const { createApp } = Vue;
createApp({
    data() {
        return {
            status: '正在初始化...',
            viewer: null,
            entity: null,
            trackEntity: null,
            positionProp: null,
            start: null,
            end: null,
            playing: false,
            speed: 1,
            jumpSec: 0,
            currentSec: 0,
            endSeconds: 0,
                         posText: '-',
             segText: '-',
             headingText: '-',
            timeMode: 'custom', // 默认使用自定义时间播放
            isSeeking: false,
                         // WebSocket相关
             websocket: null,
             websocketUrl: 'ws://127.0.0.1:6088/uam/v2/ws/uam/channel/245', // WebSocket服务器地址
             isConnected: false,
             reconnectInterval: null,
             reconnectAttempts: 0,
             maxReconnectAttempts: 5,
             wsClientType: '1', // WebSocket客户端类型
             planId: '1', // 计划ID
             schemaRequirementId: '798', // 需求ID
            
            // 实时轨迹数据
            flightTracks: [], // 将从WebSocket获取
            trackColors: [Cesium.Color.RED, Cesium.Color.BLUE, Cesium.Color.GREEN, Cesium.Color.YELLOW],
            trackEntities: {}, // 存储轨迹实体 {trackId: entity}
            aircraftEntities: {}, // 存储飞机实体 {trackId: entity}
            trackPolylines: {}, // 存储轨迹线实体 {trackId: entity}
            routeEntities: {}, // 存储航线实体 {routeId: entity}
            
                         // 实时渲染相关
             realTimeMode: true, // 实时模式
             renderInterval: null,
             lastRenderTime: 0,
                             renderDelay: 500, // 每0.5秒渲染一次新点，更好的实时性
             
             // 白膜效果相关
             whiteMask: null, // 白膜对象
             whiteMaskOpacity: 0.3, // 白膜透明度
             
             // 建筑物白膜效果相关
             buildingMaskActive: false, // 建筑物白膜是否激活
             buildingMaskOpacity: 0.3, // 建筑物白膜透明度
             
             // 白膜3D Tiles相关
             baimoTileset: null, // 白膜3D Tiles引用
             baimoWhiteMaskActive: false, // 白膜效果是否激活
             baimoMaskOpacity: 0.8, // 白膜透明度
             lastUpdateTime: 0, // 上次更新时间
                             updateThrottle: 200, // 更新节流间隔（毫秒），更好的实时性
             enableRealTimeUpdate: true, // 是否启用实时更新
                          showHistoricalTracks: true, // 是否显示历史轨迹
             enableSegmentedColors: true, // 是否启用分段颜色（飞过的轨迹用青色）
             // 面板显示控制
            leftPanelHidden: false,
            rightPanelHidden: false,
            geojsonPanelExpanded: true, // 导调信息面板是否展开

            
            // 初始定位坐标
             initialLongitude: 120.16196180060605,
             initialLatitude: 30.14332020097707,
             initialZoomLevel: 18,
             currentZoomLevel: 18, // 当前地图缩放级别
             currentMapType: '卫星地图', // 当前地图类型
             initialLocationSet: false, // 是否已经完成初始定位
             zoomUpdateTimeout: null, // 缩放级别更新防抖定时器
            // 当前选中的轨迹（用于播放）
            currentTrackIndex: 0,
            flightPath: [], // 将根据选中的轨迹动态设置
             
             // 时间轴控制相关
             playing: false, // 是否正在播放
             playbackSpeed: 1, // 播放速度
             currentTime: 0, // 当前时间（秒）
             totalDuration: 0, // 总时长（秒）
             currentTimePercent: 0, // 当前时间百分比
             playbackInterval: null, // 播放定时器
                         // 为每条轨迹创建独立的飞机实体
             // 绘制相关
             drawing: false,
             drawPositions: [], // Cartesian3
             drawPolygonEntity: null,
             drawOutlineEntity: null,
             drawHandler: null,
             polygonGeoJSON: null, // 存储多边形的GeoJSON
             _preDrawCameraLocked: false, // 绘制前的相机锁定状态
             geojsonRecords: [], // 存储所有GeoJSON记录
             batchPlanId: 1, // 批量设置方案ID
             batchNamePrefix: '多边形', // 批量设置名称前缀
             lastHeading: null, // 存储上一次的飞行方向，用于平滑处理
             taskList: [], // 任务列表数据
             taskStatus: {}, // 任务状态跟踪 {uuid: {completed: boolean, aircraftEntity: entity}}
             taskCompletionStats: { totalChecks: 0, totalTime: 0, avgTime: 0 }, // 任务完成检查性能统计
             selectedTaskInfo: null, // 选中的任务信息
             landingFieldEntities: {}, // 起降场实体
             showLandingFieldNames: false, // 是否显示起降场名称，初始化时不显示
             globalClickHandler: null, // 全局点击事件处理器
             showEditDialogFlag: false, // 是否显示编辑对话框
             currentEditData: null, // 当前编辑的数据
             currentEditTitle: '', // 当前编辑的标题
             editedExtraAttributes: {}, // 编辑中的extraAttributes数据
             vid: 660, // 仿真验证vid
             vidStatus: 2, // 仿真验证状态

             seekDebounceTimer: null, // 时间轴拖动防抖定时器
             selectedTrackId: '', // 选中的轨迹ID
             selectedTrackData: null, // 选中的轨迹数据
             showFunctionButtons: false, // 是否显示功能按钮
             continuousFollowTimer: null, // 持续跟随定时器
             realTimeMovementTimer: null, // 实时移动定时器
             currentTrackedAircraftId: null, // 当前跟踪的飞行器ID
             currentViewMode: null, // 当前视图模式
             currentTrackPoint: null, // 当前轨迹点数据
             secondTrackData: null, // 第二个轨迹数据
             previousTrackPoint: null, // 上一个轨迹点数据
             thirdLastTrackPoint: null, // 倒数第三个轨迹点数据
             fourthLastTrackPoint: null, // 倒数第四个轨迹点数据
             recentTrackPoints: [], // 最近10个轨迹点
             isRequestingTasks: false, // 是否正在请求任务列表
             isUpdatingSelection: false, // 防止循环调用的标志
             currentEnv: 'test', // 当前环境，默认选中测试环境
             apiBaseUrl: '', // 接口基础地址

             tileLoadHandler: null, // 瓦片加载事件处理器
             
             // 分页相关
             currentPage: 1, // 当前页码
             pageSize: 20, // 每页显示数量
             pageSizeOptions: [10, 20, 50, 100], // 页面大小选项
             
             // 任务列表分页相关
             currentTaskPage: 1, // 当前任务页码
             taskPageSize: 3, // 每页显示任务数量
             

        };
    },
         computed: { 
         clock() { return this.viewer ? this.viewer.clock : null; },
         trackStats() {
             if (!this.flightTracks || this.flightTracks.length === 0) return '暂无轨迹';
             
             const totalPoints = this.flightTracks.reduce((sum, track) => 
                 sum + (track && track.points ? track.points.length : 0), 0
             );
             
             const activeTracks = this.flightTracks.filter(track => {
                 if (!track || !track.points || track.points.length === 0) return false;
                 const currentTime = Date.now();
                 const trackEndTime = track.startTime + track.points[track.points.length - 1].timestamp * 1000;
                 return currentTime <= trackEndTime + 60000; // 1分钟内的轨迹认为是活跃的
             }).length;
             
             return `${this.flightTracks.length}条轨迹，${totalPoints}个点，${activeTracks}条活跃`;
         },
                   hasValidTrack() {
              return this.flightTracks && this.flightTracks.length > 0 && 
                     this.currentTrackIndex >= 0 && 
                     this.currentTrackIndex < this.flightTracks.length &&
                     this.flightTracks[this.currentTrackIndex] &&
                     this.flightTracks[this.currentTrackIndex].points &&
                     this.flightTracks[this.currentTrackIndex].points.length > 0;
          },
                     currentZoomLevelDisplay() {
               return this.currentZoomLevel;
           },
           routeCount() {
               return this.routeEntities ? Object.keys(this.routeEntities).length : 0;
           },
           sortedTaskList() {
               if (!this.taskList || this.taskList.length === 0) {
                   return [];
               }
               
               // 获取当前选中的轨迹
               let selectedTaskId = null;
               
               // 优先使用selectedTrackId
               if (this.selectedTrackId) {
                   const selectedTrack = this.flightTracks.find(t => t.id === this.selectedTrackId);
                   if (selectedTrack && selectedTrack.tid) {
                       selectedTaskId = selectedTrack.tid;
                   }
               }
               
               // 如果没有通过selectedTrackId找到，则尝试使用currentTrackIndex
               if (!selectedTaskId && this.currentTrackIndex >= 0 && this.flightTracks[this.currentTrackIndex]) {
                   const currentTrack = this.flightTracks[this.currentTrackIndex];
                   if (currentTrack && currentTrack.tid) {
                       selectedTaskId = currentTrack.tid;
                   }
               }
               
               // 如果没有选中的任务，返回原始列表
               if (!selectedTaskId) {
                   return this.taskList;
               }
               
               // 对任务列表进行排序：当前选中的任务排在最前面
               const sortedTasks = [...this.taskList].sort((a, b) => {
                   // 如果任务a是当前选中的任务，排在最前面
                   if (a.uuid === selectedTaskId) {
                       return -1;
                   }
                   // 如果任务b是当前选中的任务，排在最前面
                   if (b.uuid === selectedTaskId) {
                       return -1; // 修改为-1，确保选中的任务总是排在最前面
                   }
                   // 其他任务保持原有顺序
                   return 0;
               });
               
               return sortedTasks;
           },
           // 分页后的任务列表
           paginatedTaskList() {
               const sorted = this.sortedTaskList;
               const startIndex = (this.currentPage - 1) * this.pageSize;
               const endIndex = startIndex + this.pageSize;
               return sorted.slice(startIndex, endIndex);
           },
           // 总页数
           totalPages() {
               return Math.ceil(this.sortedTaskList.length / this.pageSize);
           },
           // 分页信息
           paginationInfo() {
               const total = this.sortedTaskList.length;
               const start = (this.currentPage - 1) * this.pageSize + 1;
               const end = Math.min(this.currentPage * this.pageSize, total);
               return `${start}-${end} / ${total}`;
           },
           
           // 任务列表分页相关计算属性
           paginatedTaskList() {
               if (!this.sortedTaskList || this.sortedTaskList.length === 0) {
                   return [];
               }
               const startIndex = (this.currentTaskPage - 1) * this.taskPageSize;
               const endIndex = startIndex + this.taskPageSize;
               return this.sortedTaskList.slice(startIndex, endIndex);
           },
           
           // 任务列表总页数
           totalTaskPages() {
               return Math.ceil(this.sortedTaskList.length / this.taskPageSize);
           }
     },
    mounted() { 
                 this.initCesium(); 
         this.updateWebSocketUrl(); // 根据环境设置WebSocket地址
         // 不再直接连接WebSocket，而是先获取任务列表
         // 不再直接启动实时渲染，而是等待任务列表数据加载后再启动
         
         // 添加飞行器点击事件监听器
         this.setupAircraftClickHandler();
         
         // 调试信息
         //// console.log('应用已挂载，飞行器点击事件已设置');
         
         // 页面加载后，先调用获取任务按钮的功能
         this.sendTaskMessage();
         
        //  setTimeout(() => {
             //console.log('延迟检查 - 轨迹数量:', this.flightTracks ? this.flightTracks.length : 0);
             //console.log('延迟检查 - 飞行器实体数量:', this.aircraftEntities ? Object.keys(this.aircraftEntities).length : 0);
         //}, 3000);
    },
    
    watch: {
        // 当选中轨迹变化时，清除缓存并跳转到对应任务页面
        selectedTrackId(newVal, oldVal) {
            if (newVal !== oldVal) {
                this.clearSelectedTaskCache();
                // 如果选中了新的轨迹，跳转到对应任务页面
                if (newVal) {
                    const selectedTrack = this.flightTracks.find(t => t.id === newVal);
                    if (selectedTrack && selectedTrack.tid) {
                        this.goToTaskPage(selectedTrack.tid);
                    }
                }
            }
        },
        
                 // 当任务列表变化时，清除缓存
         taskList() {
             this.clearSelectedTaskCache();
         },
         
         // 当轨迹数据变化时，清除性能缓存
         flightTracks() {
             this.clearPerformanceCache();
         }
    },
                   beforeUnmount() {
          this.disconnectWebSocket();
          if (this.renderInterval) {
              clearInterval(this.renderInterval);
          }
          if (this.playbackInterval) {
              clearInterval(this.playbackInterval);
          }
          if (this.zoomUpdateTimeout) {
              clearTimeout(this.zoomUpdateTimeout);
          }
          if (this.seekDebounceTimer) {
              clearTimeout(this.seekDebounceTimer);
          }
          
          // 清理相机变化监听器
          if (this.cameraChangeListener) {
              this.viewer.camera.changed.removeEventListener(this.cameraChangeListener);
          }

          // 清理全局点击事件处理器
          if (this.globalClickHandler) {
              this.globalClickHandler.destroy();
              this.globalClickHandler = null;
          }
          
          // 清理瓦片加载事件处理器
          if (this.tileLoadHandler && this.viewer && this.viewer.scene && this.viewer.scene.globe) {
              this.viewer.scene.globe.tileLoadProgressEvent.removeEventListener(this.tileLoadHandler);
              this.tileLoadHandler = null;
          }
          
          // 清理飞行器点击事件处理器
          if (this.aircraftClickHandler) {
              this.aircraftClickHandler.destroy();
              this.aircraftClickHandler = null;
          }
          
          // 清理持续跟随定时器
          if (this.continuousFollowTimer) {
              clearInterval(this.continuousFollowTimer);
              this.continuousFollowTimer = null;
          }
      },
    methods: {
        // 面板显示控制
        toggleLeftPanel() {
            this.leftPanelHidden = !this.leftPanelHidden;
        },
        
        toggleRightPanel() {
            this.rightPanelHidden = !this.rightPanelHidden;
        },
        
        // 导调信息面板展开/收缩控制，同时控制所有面板
        toggleGeojsonPanel() {
            this.geojsonPanelExpanded = !this.geojsonPanelExpanded;
            // 同时控制右侧面板、任务列表、轨迹属性面板的显示/隐藏
            this.rightPanelHidden = !this.geojsonPanelExpanded;
        },
        

        
        // 选择导调选项
        selectDispatchOption(record, option) {
            // 如果选择的是同一个选项，则取消选择
            if (record.selectedDispatchOption === option) {
                record.selectedDispatchOption = null;
            } else {
                record.selectedDispatchOption = option;
            }
            
            // 根据选择的选项执行相应的操作
            switch (option) {
                case 'local_avoidance':
                    this.sendLocalAvoidance(record);
                    break;
                case 'forced_landing':
                    this.sendForcedLanding(record);
                    break;
                case 'return_home':
                    this.sendReturnHome(record);
                    break;
                case 'crash':
                    this.sendCrash(record);
                    break;
            }
        },
        
        // 发送迫降消息
        sendForcedLanding(record) {
            this.sendDispatchMessage(8, record);
        },
        
        // 发送返航消息
        sendReturnHome(record) {
            this.sendDispatchMessage(7, record);
        },
        
        // 发送坠毁消息
        sendCrash(record) {
            this.sendDispatchMessage(9, record);
        },
        
                 // 发送导调消息的统一方法
         sendDispatchMessage(wsClientType, record) {
             try {
                 // 检查实时任务数量
                 const activeTaskCount = this.flightTracks.length;
                 if (activeTaskCount === 0 || !activeTaskCount) {
                     this.status = '当前没有实时任务，无法发送导调消息';
                     alert('当前没有实时任务，无法发送导调消息！请先获取任务数据。');
                     return;
                 }
                 
                 // 获取当前选中的轨迹ID
                 const selectedTid = this.selectedTrackId;
                 if (!selectedTid) {
                     this.status = '请先选择一个轨迹';
                     alert('请先在右侧轨迹属性面板中选择一个轨迹，然后再点击导调按钮！');
                     return;
                 }
                 
                 // 查找对应的轨迹数据，获取tid值
                 const selectedTrack = this.flightTracks.find(track => track.id === selectedTid);
                 if (!selectedTrack) {
                     this.status = '未找到选中的轨迹数据';
                     alert('未找到选中的轨迹数据，请重新选择轨迹！');
                     return;
                 }
                 
                 // 使用轨迹的tid值，如果没有tid则使用id
                 const tidValue = selectedTrack.tid || selectedTrack.id;
                 
                 // 构建消息格式
                 const message = {
                     wsClientType: wsClientType.toString(),
                     planId: this.planId || "3017", // 使用当前方案ID或默认值
                     tid: [tidValue.toString()], // 从右边轨迹下拉框选中的tid值
                     time: this.currentTrackPoint ? (this.currentTrackPoint.timestamp_absolute || this.currentTrackPoint.ts || this.currentTrackPoint.timestamp) : Math.floor(Date.now() / 1000) // 添加时间戳字段
                 };
                 
                 // 如果是局部避障消息(wsClientType=2)，添加polygon字段
                 if (wsClientType === 2 && record && record.geojson) {
                     message.polygon = record.geojson;
                     console.log('添加polygon字段到局部避障消息:', record.geojson);
                 }
                 
                 
                 // 发送WebSocket消息
                 if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
                     this.websocket.send(JSON.stringify(message));
                     this.status = `已发送导调消息: wsClientType=${wsClientType}, tid=${tidValue}`;
                     console.log('WebSocket消息发送成功');
                 } else {
                     this.status = 'WebSocket连接未建立，无法发送消息';
                     // console.warn('WebSocket未连接，当前状态:', this.websocket ? this.websocket.readyState : 'null');
                     alert('WebSocket连接未建立，无法发送消息，请检查WebSocket连接状态！');
                 }
                 
             } catch (error) {
                 // console.error('发送导调消息失败:', error);
                 this.status = '发送导调消息失败';
                 alert('发送导调消息失败: ' + error.message);
             }
         },
        

        
        // 安全缩放到目标：兼容 Promise / 非 Promise 返回
        safeZoomTo(target) {
            try {
                const res = this.viewer.zoomTo(target);
                if (res && typeof res.then === 'function') {
                    res.catch(() => {
                        this.viewer.camera.setView({
                            destination: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 2000000),
                            orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0.0 }
                        });
                    });
                }
            } catch (_) {
                this.viewer.camera.setView({
                    destination: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 2000000),
                    orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0.0 }
                });
            }
        },
        // 将相机定位到轨迹第一个点位置
        focusFirstPoint() {
            if (!this.flightPath || this.flightPath.length === 0) return;
            const p0 = this.flightPath[0];
             
             // 验证坐标的有效性
             if (p0 && 
                 typeof p0.longitude === 'number' && !isNaN(p0.longitude) &&
                 typeof p0.latitude === 'number' && !isNaN(p0.latitude) &&
                 p0.longitude >= -180 && p0.longitude <= 180 &&
                 p0.latitude >= -90 && p0.latitude <= 90) {
                 
            const height = Math.max(30000, (p0.altitude || 0) + 80000);
                 try {
            this.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromDegrees(p0.longitude, p0.latitude, height),
                orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO + 0.2, roll: 0.0 }
            });
                     
                     // 更新状态
                     this.status = `已定位到轨迹起点: ${p0.longitude.toFixed(4)}, ${p0.latitude.toFixed(4)}`;
                 } catch (e) {
                     // 定位到起点失败
                     this.status = '定位到起点失败';
                 }
             }
        },
        
        // 定位到第一条轨迹的第一个点
        focusToFirstTrackPoint() {
            if (this.flightTracks.length === 0) return;
            
            const firstTrack = this.flightTracks[0];
            if (!firstTrack.points || firstTrack.points.length === 0) return;
            
            const firstPoint = firstTrack.points[0];
            
            // 验证坐标的有效性
            if (firstPoint && 
                typeof firstPoint.longitude === 'number' && !isNaN(firstPoint.longitude) &&
                typeof firstPoint.latitude === 'number' && !isNaN(firstPoint.latitude) &&
                firstPoint.longitude >= -180 && firstPoint.longitude <= 180 &&
                firstPoint.latitude >= -90 && firstPoint.latitude <= 90) {
                
                const height = Math.max(30000, (firstPoint.altitude || 0) + 80000);
                try {
                    this.viewer.camera.setView({
                        destination: Cesium.Cartesian3.fromDegrees(firstPoint.longitude, firstPoint.latitude, height),
                        orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO + 0.2, roll: 0.0 }
                    });
                    
                    // 更新状态
                    this.status = `已定位到第一条轨迹起点: ${firstPoint.longitude.toFixed(4)}, ${firstPoint.latitude.toFixed(4)}`;
                } catch (e) {
                    // 定位到第一条轨迹起点失败
                    this.status = '定位到第一条轨迹起点失败';
                }
            }
        },
        
        initCesium() {
            try {
                // 参考test-cesium.html的成功实现
                this.viewer = new Cesium.Viewer('cesiumContainer', {
                    terrain: Cesium.Terrain.fromWorldTerrain(),
                    baseLayerPicker: true,
                    geocoder: true,
                    homeButton: true,
                    sceneModePicker: true,
                    navigationHelpButton: true,
                    animation: true,
                    timeline: true,
                    fullscreenButton: true,
                    infoBox: true,
                    selectionIndicator: true,
                });
                
                // 设置初始视角到杭州
                this.viewer.camera.setView({
                    destination: Cesium.Cartesian3.fromDegrees(120.16196180060605, 30.14332020097707, 1000000),
                    orientation: {
                        heading: 0.0,
                        pitch: -Cesium.Math.PI_OVER_TWO,
                        roll: 0.0
                    }
                });
                
                // 设置地图类型
                this.currentMapType = 'Cesium 默认地图';
                this.playbackSpeed = 1;
                

                
                this.status = 'Cesium 地图加载完成';
                
                // 设置相机稳定性，防止频繁跳动
                this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false;
                this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = 1000;
                this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000000;
                
                // 禁用所有可能导致相机自动移动的功能
                this.viewer.scene.screenSpaceCameraController.enableRotate = true;
                this.viewer.scene.screenSpaceCameraController.enableTranslate = true;
                this.viewer.scene.screenSpaceCameraController.enableZoom = true;
                this.viewer.scene.screenSpaceCameraController.enableTilt = true;
                this.viewer.scene.screenSpaceCameraController.enableLook = true;
                
                // 禁用相机自动跟踪实体
                this.viewer.trackedEntity = undefined;
                
                // 监听trackedEntity变化，防止自动跟踪
                this.viewer.trackedEntityChanged.addEventListener(() => {
                    // 如果检测到有实体被设置为跟踪，立即清除
                    if (this.viewer.trackedEntity) {
                        this.viewer.trackedEntity = undefined;
                    }
                });
                
                // 禁用Cesium的自动缩放功能
                this.viewer.scene.screenSpaceCameraController._aggregator._eventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                this.viewer.scene.screenSpaceCameraController._aggregator._eventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
                
                // 禁用实体点击时的自动缩放功能
                this.viewer.screenSpaceEventHandler.setInputAction((event) => {
                    // 检查是否点击了实体
                    const pickedObject = this.viewer.scene.pick(event.position);
                    if (pickedObject && pickedObject.id) {
                        // 如果点击的是实体，阻止默认的缩放行为
                        // 但仍然允许选择实体（用于信息显示）
                        this.viewer.selectedEntity = pickedObject.id;
                        return false;
                    }
                    // 如果点击的是地图，清除选择并允许正常操作
                    this.viewer.selectedEntity = undefined;
                    return true;
                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                
                // 完全禁用所有自动缩放功能
                const originalZoomTo = this.viewer.zoomTo.bind(this.viewer);
                this.viewer.zoomTo = (target, options) => {
                    // 完全阻止所有自动缩放
                    this.status = '自动缩放已被禁用';
                    return Promise.resolve();
                };
                
                // 重写flyTo方法
                const originalFlyTo = this.viewer.flyTo.bind(this.viewer);
                this.viewer.flyTo = (target, options) => {
                    // 完全阻止所有自动飞行
                    this.status = '自动飞行已被禁用';
                    return Promise.resolve();
                };
                
                // 禁用Cesium的默认实体点击行为
                this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
                
                // 完全禁用Cesium的自动行为
                
                // 设置场景参数，确保实体正确显示
                this.viewer.scene.globe.enableLighting = false; // 禁用光照，避免影响实体显示
                this.viewer.scene.fog.enabled = false; // 禁用雾效，避免影响实体显示
                
                // 设置实体显示参数
                this.viewer.scene.globe.depthTestAgainstTerrain = false; // 禁用地形深度测试，确保实体显示
                
                                 // 设置标签显示参数
                 this.viewer.scene.globe.showGroundAtmosphere = false; // 禁用地面大气效果，避免影响标签显示
                 
                 // 监听相机变化，确保起降场始终显示
                 this.viewer.camera.changed.addEventListener(() => {
                     // 延迟执行，确保相机变化完成后再刷新
                     setTimeout(() => {
                         this.refreshLandingFieldDisplay();
                     }, 100);
                 });
                this.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false;
                this.viewer.scene.screenSpaceCameraController.enableRotate = true;
                this.viewer.scene.screenSpaceCameraController.enableTranslate = true;
                this.viewer.scene.screenSpaceCameraController.enableZoom = true;
                this.viewer.scene.screenSpaceCameraController.enableTilt = true;
                this.viewer.scene.screenSpaceCameraController.enableLook = true;
                
                // 只禁用自动缩放相关的功能，保留手动缩放
                this.viewer.scene.screenSpaceCameraController._aggregator._eventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                this.viewer.scene.screenSpaceCameraController._aggregator._eventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
                // 不删除WHEEL事件，保留鼠标滚轮缩放功能
                
                // 添加相机位置锁定机制
                this.cameraLocked = false;
                this.lastCameraPosition = null;
                this.cameraPositionLocked = false;
                this.forceCameraLock = false;
                
                // 强制相机位置保持
                this.viewer.scene.postRender.addEventListener(() => {
                    if (this.forceCameraLock && this.lastCameraPosition) {
                        // 强制保持相机位置，不允许任何变化
                        this.viewer.camera.setView({
                            destination: this.lastCameraPosition.destination,
                            orientation: this.lastCameraPosition.orientation
                        });
                    }
                });
                
                // 添加鼠标滚轮事件监听，在强制锁定时阻止缩放
                this.viewer.screenSpaceEventHandler.setInputAction((event) => {
                    if (this.forceCameraLock) {
                        // 如果强制锁定，阻止滚轮缩放
                        return false;
                    }
                    // 否则允许正常缩放
                    return true;
                }, Cesium.ScreenSpaceEventType.WHEEL);
                
                // 监听相机变化事件
                this.cameraChangeListener = () => {
                    if (this.forceCameraLock && this.lastCameraPosition && !this.drawing) {
                        // 只有在非绘制状态下才强制恢复相机位置
                        setTimeout(() => {
                            this.viewer.camera.setView({
                                destination: this.lastCameraPosition.destination,
                                orientation: this.lastCameraPosition.orientation
                            });
                        }, 0);
                    }
                    
                    // 实时更新缩放级别
                    this.updateCurrentZoomLevelRealtime();
                };
                this.viewer.camera.changed.addEventListener(this.cameraChangeListener);
                
            } catch (e) { 
                this.status = '初始化失败: ' + (e.message || e);
            }
        },
        
         // 定位到初始位置
         focusToInitialLocation() {
             try {
                 const longitude = this.initialLongitude;
                 const latitude = this.initialLatitude;
                 const zoomLevel = this.initialZoomLevel;
                 
                 // 计算13级地图对应的相机高度
                 const height = this.calculateHeightForZoomLevel(zoomLevel);
                 
                 this.viewer.camera.setView({
                     destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
                     orientation: { 
                         heading: 0.0, 
                         pitch: -Cesium.Math.PI_OVER_TWO + 0.1, 
                         roll: 0.0 
                     }
                 });
                 
                 // console.log(`地图已定位到: ${longitude}, ${latitude}, 缩放级别: ${zoomLevel}`);
                 this.status = `地图已定位到指定坐标 (${longitude.toFixed(6)}, ${latitude.toFixed(6)})，缩放级别: ${zoomLevel}`;
                 
                 // 更新当前缩放级别
                 this.currentZoomLevel = zoomLevel;
                 
                 // 标记初始定位已完成
                 this.initialLocationSet = true;
             } catch (e) {
                 // console.warn('定位到初始位置失败:', e);
                 this.status = '定位到初始位置失败';
             }
         },
         
         // 根据缩放级别计算相机高度
         calculateHeightForZoomLevel(zoomLevel) {
             // 18级地图对应的相机高度大约为 250 米
             // 使用更精确的计算方法
             const earthRadius = 6371000; // 地球半径（米）
             const tileSize = 256; // 瓦片大小
             const pixelsPerTile = tileSize * Math.pow(2, zoomLevel);
             const metersPerPixel = (2 * Math.PI * earthRadius) / pixelsPerTile;
             const height = metersPerPixel * 1000; // 1000像素对应的高度
             
             return Math.max(height, 5000); // 最小高度5000米
         },
         
         // 更新当前缩放级别
         updateCurrentZoomLevel() {
             if (!this.viewer) return;
             
             try {
                 const camera = this.viewer.camera;
                 const height = camera.positionCartographic.height;
                 
                 // 简化的缩放级别计算方法
                 // 18级对应约250米高度，每级高度减半
                 const baseHeight = 250;
                 const baseZoom = 18;
                 const zoomLevel = baseZoom - Math.log2(height / baseHeight);
                 
                 const newZoomLevel = Math.max(0, Math.round(zoomLevel));
                 
                 // 只有当缩放级别真正改变时才更新
                 if (newZoomLevel !== this.currentZoomLevel) {
                     this.currentZoomLevel = newZoomLevel;
                     
                     // 如果还没有完成初始定位，标记为已完成
                     if (!this.initialLocationSet) {
                         this.initialLocationSet = true;
                     }
                 }
             } catch (e) {
                 console.warn('更新缩放级别失败:', e);
             }
         },
         
         // 重置到初始位置
         resetToInitialLocation() {
             // 重置初始定位标记，允许重新定位
             this.initialLocationSet = false;
             this.focusToInitialLocation();
         },
         
         // 手动更新缩放级别
         forceUpdateZoomLevel() {
             this.updateCurrentZoomLevel();
         },
         
         // 实时更新缩放级别（带防抖）
         updateCurrentZoomLevelRealtime() {
             if (!this.viewer) return;
             
             // 清除之前的防抖定时器
             if (this.zoomUpdateTimeout) {
                 clearTimeout(this.zoomUpdateTimeout);
             }
             
             // 设置防抖定时器，50ms后更新
             this.zoomUpdateTimeout = setTimeout(() => {
                 this.updateCurrentZoomLevel();
             }, 50);
         },
        
        // ================= WebSocket相关 =================
        connectWebSocket() {
            try {
                this.websocket = new WebSocket(this.websocketUrl);
                
                                                 this.websocket.onopen = () => {
                    this.isConnected = true;
                    this.reconnectAttempts = 0;
                    this.status = 'WebSocket已连接，正在初始化数据...';
                    // console.log('WebSocket连接成功');
                    
                    // 连接成功后，自动获取起降场、航线和任务信息
                    this.initializeDataAfterConnection();
                    
                    // 如果是自动重连成功，显示特殊提示
                    if (this.reconnectInterval) {
                        this.status = 'WebSocket自动重连成功，正在初始化数据...';
                        clearInterval(this.reconnectInterval);
                        this.reconnectInterval = null;
                    }
                };
                
                this.websocket.onmessage = (event) => {
                    this.handleWebSocketMessage(event.data);
                };
                
                this.websocket.onclose = () => {
                    this.isConnected = false;
                    this.status = 'WebSocket连接断开，尝试重连...';
                                         // console.log('WebSocket连接断开');
                    this.scheduleReconnect();
                };
                
                this.websocket.onerror = (error) => {
                    this.status = 'WebSocket连接错误';
                };
                
            } catch (error) {
                console.error('WebSocket连接失败:', error);
                this.status = 'WebSocket连接失败';
                this.scheduleReconnect();
            }
        },
        
        disconnectWebSocket() {
            if (this.websocket) {
                this.websocket.close();
                this.websocket = null;
            }
            if (this.reconnectInterval) {
                clearInterval(this.reconnectInterval);
                this.reconnectInterval = null;
            }
        },
        
        reconnectWebSocket() {
            this.disconnectWebSocket();
            this.reconnectAttempts = 0;
            this.connectWebSocket();
        },
        
                 scheduleReconnect() {
             if (this.reconnectAttempts >= this.maxReconnectAttempts) {
                 this.status = 'WebSocket重连失败，请检查服务器状态';
                 return;
             }
             
             this.reconnectAttempts++;
             const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000); // 指数退避
             
             this.reconnectInterval = setTimeout(() => {
                 this.status = `尝试重连WebSocket (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`;
                 this.connectWebSocket();
             }, delay);
         },
         
         // WebSocket连接成功后自动初始化数据
         initializeDataAfterConnection() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法初始化数据');
                 return;
             }
             
             console.log('开始自动初始化数据...');
             
             // 延迟执行，确保WebSocket连接稳定
             setTimeout(() => {
                 // 1. 先获取起降场信息
                 //this.sendLandingFieldMessageAfterConnection();
             }, 200);
             
             setTimeout(() => {
                 // 2. 再获取航线信息
                 this.sendInitMessageAfterConnection();
             }, 400);
             
             setTimeout(() => {
                 // 3. 最后获取任务信息
                 this.sendTaskMessageAfterConnection();
             }, 600);
             
             // 确保实时更新已启用并开始渲染实时估计点数据
             setTimeout(() => {
                 // 4. 启用实时更新并开始渲染
                 if (!this.enableRealTimeUpdate) {
                     this.enableRealTimeUpdate = true;
                     //console.log('自动启用实时更新');
                 }
                 
                 // 确保渲染间隔已设置
                 if (!this.renderInterval) {
                     this.renderInterval = setInterval(() => {
                         this.renderNewPoints();
                     }, this.renderDelay);
                    // console.log('开始渲染实时估计点数据');
                 }
             }, 800);
             setTimeout(() => {
                 if (!this.enableRealTimeUpdate) {
                     this.enableRealTimeUpdate = true;
                     this.toggleRealTimeUpdate();
                    // console.log('已自动启用实时更新');
                 }
                 
                 // 开始渲染实时估计点数据
                 if (!this.renderInterval && this.enableRealTimeUpdate) {
                     this.renderInterval = setInterval(() => {
                         this.renderNewPoints();
                     }, this.renderDelay);
                    // console.log('已开始渲染实时估计点数据');
                 }
             }, 800);
         },
         
         // 连接后发送起降场信息请求
         sendLandingFieldMessageAfterConnection() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法发送起降场信息请求');
                 return;
             }
             
             // 先清空现有的起降场，避免重复加载
             this.clearAllLandingFieldsWithoutConfirm();
             
             try {
                 const landingFieldMessage = {
                     wsClientType: 4,
                     schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                 };
                 this.websocket.send(JSON.stringify(landingFieldMessage));
                 this.status = '已发送起降场信息请求...';
                // console.log('已发送起降场信息请求:', landingFieldMessage);
             } catch (error) {
                 console.error('发送起降场信息请求失败:', error);
                 this.status = '发送起降场信息请求失败';
             }
         },
         
         // 连接后发送航线信息请求
         sendInitMessageAfterConnection() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法获取航线');
                 return;
             }
             
             // 先清空现有的航线，避免重复加载
             this.clearAllRoutesWithoutConfirm();
             
             try {
                 const initMessage = {
                     wsClientType: this.wsClientType,
                     planId: parseInt(this.planId) || 1,
                     schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                 };
                 this.websocket.send(JSON.stringify(initMessage));
                 this.status = '已发送航线信息请求...';
                // console.log('已发送航线信息请求:', initMessage);
             } catch (error) {
                 console.error('获取航线失败:', error);
                 this.status = '获取航线失败';
             }
         },
         
         // 获取需求对应的航线
         sendInitMessage() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法获取航线');
                 return;
             }
             
             // 先清空现有的航线，避免重复加载
             this.clearAllRoutesWithoutConfirm();
             
             try {
                  const initMessage = {
                                           wsClientType: this.wsClientType,
                     planId: parseInt(this.planId) || 1,
                     schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                  };
                  this.websocket.send(JSON.stringify(initMessage));
                  // console.log('已发送获取航线请求:', initMessage);
                  this.status = '已清空现有航线，正在获取新的航线数据...';
              } catch (error) {
                  console.error('获取航线失败:', error);
                  this.status = '获取航线失败';
              }
         },
         
         // 发送起降场信息请求
         sendLandingFieldMessage() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法发送起降场信息请求');
                 return;
             }
             
             // 先清空现有的起降场，避免重复加载
             this.clearAllLandingFieldsWithoutConfirm();
             
             try {
                 const landingFieldMessage = {
                     wsClientType: 4,
                     schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                 };
                 this.websocket.send(JSON.stringify(landingFieldMessage));
                 // 已发送起降场信息请求
                 this.status = '已清空现有起降场，正在获取新的起降场数据...';
             } catch (error) {
                 console.error('发送起降场信息请求失败:', error);
                 this.status = '发送起降场信息请求失败';
             }
         },
         
         // 发送获取任务信息请求
         sendTaskMessage() {
             
             // 如果WebSocket未连接，先连接WebSocket
             if (!this.isConnected || !this.websocket) {
                 console.log('WebSocket未连接，先连接WebSocket');
                 this.connectWebSocket();
                 
                 // 连接后等待一小段时间再发送请求
                 setTimeout(() => {
                     this.sendTaskMessageAfterConnection();
                 }, 500);
                 return;
             }
             
             this.sendTaskMessageAfterConnection();
         },
         
         // WebSocket连接后发送任务信息请求
         sendTaskMessageAfterConnection() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('❌ WebSocket仍未连接，无法发送任务信息请求');
                 return;
             }
             
             try {
                 const taskMessage = {
                     wsClientType: 5,
                     schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                 };
                 
                 this.websocket.send(JSON.stringify(taskMessage));
                 this.status = '已发送任务信息请求...';
             } catch (error) {
                 console.error('❌ 发送任务信息请求失败:', error);
                 this.status = '发送任务信息请求失败';
             }
         },
         
         // 发送仿真验证消息
         sendSimulationMessage() {
             if (!this.isConnected || !this.websocket) {
                 console.warn('WebSocket未连接，无法发送仿真验证消息');
                 return;
             }
             
             try {
                 const simulationMessage = {
                     wsClientType: 6,
                     vid: parseInt(this.vid) || 660,
                     vidStatus: parseInt(this.vidStatus) || 2
                 };
                 this.websocket.send(JSON.stringify(simulationMessage));
                 // console.log('已发送仿真验证消息:', simulationMessage);
                 this.status = '已发送仿真验证消息，已清空实时轨迹，航线保持不变...';
                 
                 // 只清空实时轨迹，不清空航线
                 this.clearAllTracksWithoutConfirm();
                 
                 // 不再清空方案ID，保持航线相关数据
                 
             } catch (error) {
                 console.error('发送仿真验证消息失败:', error);
                 this.status = '发送仿真验证消息失败';
             }
         },
        
                 handleWebSocketMessage(data) {
             try {
                 const message = JSON.parse(data);
                 
                 // 处理不同的消息类型
                 if (message.msgType === 1 && message.data && Array.isArray(message.data)) {
                     // msgType = 1: 实时轨迹数据
                     this.processTrackData(message.data);
                 } else if (message.msgType === 2 && message.data) {
                     // msgType = 2: 实时消息记录（已禁用）
                     // this.processMessageLog(message.data);
                 } else if (message.msgType === 3 && message.data) {
                     // msgType = 3: 航线信息
                     this.processRouteData(message.data);
                 } else if (message.msgType === 4 && message.data) {
                     // msgType = 4: 起降场信息
                     // 收到起降场消息
                     this.processLandingFieldData(message.data);
                 } else if (message.msgType === 5 && message.data) {
                     // msgType = 5: 任务列表信息
                     this.processTaskListData(message.data);
                 } else if (message.code === 200 && message.data && message.data.list) {
                     // 兼容旧格式
                     this.processTrackData(message.data.list);
                 } else {
                     // console.log('收到WebSocket消息:', message);
                 }
             } catch (error) {
                 console.error('解析WebSocket消息失败:', error);
             }
         },
         

         

         

         
         // 添加白膜效果
         addWhiteMask() {
             // 创建白色半透明遮罩
             const whiteMask = this.viewer.scene.primitives.add(new Cesium.Primitive({
                 geometryInstances: new Cesium.GeometryInstance({
                     geometry: new Cesium.RectangleGeometry({
                         rectangle: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),
                         vertexFormat: Cesium.VertexFormat.ALL
                     })
                 }),
                 appearance: new Cesium.MaterialAppearance({
                     material: Cesium.Material.fromType('Color', {
                         color: new Cesium.Color(1.0, 1.0, 1.0, this.whiteMaskOpacity) // 使用当前透明度设置
                     })
                 })
             }));
             
             this.whiteMask = whiteMask;
             this.status = '已添加白膜效果';
         },
         
         // 移除白膜效果
         removeWhiteMask() {
             if (this.whiteMask) {
                 this.viewer.scene.primitives.remove(this.whiteMask);
                 this.whiteMask = null;
                 this.status = '已移除白膜效果';
             }
         },
         
         // 调整白膜透明度
         adjustWhiteMaskOpacity(opacity) {
             if (this.whiteMask && this.whiteMask.appearance) {
                 this.whiteMask.appearance.material.uniforms.color.alpha = opacity;
                 this.whiteMaskOpacity = opacity;
                 this.status = `白膜透明度已调整为: ${Math.round(opacity * 100)}%`;
             }
         },
         
         // 添加建筑物白膜效果
         addBuildingWhiteMask() {
             
             
             // 获取所有3D Tiles图层
             const tilesets = this.viewer.scene.primitives._primitives.filter(primitive => 
                 primitive instanceof Cesium.Cesium3DTileset
             );
             
             
             
             if (tilesets.length === 0) {
                 this.status = '未找到3D建筑物图层，请先加载3D Tiles';
 
                 return;
             }
             
             // 为每个3D Tiles图层应用白膜材质
             tilesets.forEach((tileset, index) => {
                 console.log(`为第${index + 1}个图层应用白膜，透明度: ${this.buildingMaskOpacity}`);
                 
                 tileset.style = new Cesium.Cesium3DTileStyle({
                     color: {
                         conditions: [
                             [true, `color("white", ${this.buildingMaskOpacity})`]
                         ]
                     }
                 });
             });
             
             this.buildingMaskActive = true;
             this.status = `已为 ${tilesets.length} 个建筑物图层添加白膜效果`;
             console.log('建筑物白膜添加完成');
         },
         
         // 移除建筑物白膜效果
         removeBuildingWhiteMask() {
             // 获取所有3D Tiles图层
             const tilesets = this.viewer.scene.primitives._primitives.filter(primitive => 
                 primitive instanceof Cesium.Cesium3DTileset
             );
             
             // 移除样式，恢复原始外观
             tilesets.forEach(tileset => {
                 tileset.style = undefined;
             });
             
             this.buildingMaskActive = false;
             this.status = '已移除建筑物白膜效果';
         },
         
         // 调整建筑物白膜透明度
         adjustBuildingMaskOpacity(opacity) {
             if (!this.buildingMaskActive) return;
             
             this.buildingMaskOpacity = opacity;
             console.log('调整建筑物白膜透明度:', opacity);
             
             // 获取所有3D Tiles图层
             const tilesets = this.viewer.scene.primitives._primitives.filter(primitive => 
                 primitive instanceof Cesium.Cesium3DTileset
             );
             
             // 更新样式透明度
             tilesets.forEach((tileset, index) => {
                 console.log(`更新第${index + 1}个图层的透明度: ${opacity}`);
                 tileset.style = new Cesium.Cesium3DTileStyle({
                     color: {
                         conditions: [
                             [true, `color("white", ${opacity})`]
                         ]
                     }
                 });
             });
             
             this.status = `建筑物白膜透明度已调整为: ${Math.round(opacity * 100)}%`;
         },
         
         // 加载3D建筑物图层（用于测试）
         load3DBuildings() {
             try {
                 console.log('开始加载3D建筑物...');
                 
                 // 加载Cesium World Terrain的3D建筑物
                 const tileset = this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
                     url: Cesium.IonResource.fromAssetId(96188), // Cesium World Buildings
                     maximumScreenSpaceError: 16,
                     maximumMemoryUsage: 512
                 }));
                 
                 // 定位到建筑物区域
                 tileset.readyPromise.then(() => {
                     console.log('3D建筑物加载成功');
                     this.viewer.zoomTo(tileset);
                     this.status = '已加载3D建筑物图层';
                 }).catch(error => {
                     console.error('加载3D建筑物失败:', error);
                     this.status = '加载3D建筑物失败';
                 });
                 
             } catch (error) {
                 console.error('加载3D建筑物失败:', error);
                 this.status = '加载3D建筑物失败';
             }
         },
         
         // 加载白膜3D Tiles
         async loadBaimoTileset() {
             try {
                 console.log('开始加载白膜3D Tiles...');
                 this.status = '正在加载白膜3D Tiles...';
                 
                 const tilesetUrl = 'http://211.159.175.30:8011/baimo_tileset/2/tileset.json';
                 
                 // 先检查网络连接
                 try {
                     const response = await fetch(tilesetUrl, { method: 'HEAD' });
                     if (!response.ok) {
                         throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                     }
                     console.log('网络连接检查通过');
                 } catch (networkError) {
                     console.error('网络连接失败:', networkError);
                     this.status = '网络连接失败，请检查服务器地址或网络连接';
                     return;
                 }
                 
                 // 使用 fromUrl 方法创建白膜3D Tiles
                 const baimoTileset = await Cesium.Cesium3DTileset.fromUrl(tilesetUrl, {
                     maximumScreenSpaceError: 16,
                     maximumMemoryUsage: 512
                 });
                 
                 // 添加到场景
                 await this.viewer.scene.primitives.add(baimoTileset);
                 
                 // 获取tileset的边界信息
                 const boundingSphere = baimoTileset.boundingSphere;
                 const boundingVolume = baimoTileset.root.boundingVolume;
                 
                 // console.log('白膜3D Tiles边界信息:', {
                 //     boundingSphere: boundingSphere,
                 //     boundingVolume: boundingVolume,
                 //     center: boundingSphere ? boundingSphere.center : null,
                 //     radius: boundingSphere ? boundingSphere.radius : null
                 // });
                 
                 // 尝试多种定位方式
                 try {
                     // 方式1: 使用zoomTo
                     await this.viewer.zoomTo(baimoTileset);
                     // console.log('使用zoomTo定位成功');
                 } catch (zoomError) {
                     // console.warn('zoomTo失败，尝试手动定位:', zoomError);
                     
                     // 方式2: 手动设置相机位置
                     if (boundingSphere) {
                         const center = boundingSphere.center;
                         const radius = boundingSphere.radius;
                         
                         this.viewer.camera.setView({
                             destination: center,
                             orientation: {
                                 heading: 0.0,
                                 pitch: -Cesium.Math.PI_OVER_TWO,
                                 roll: 0.0
                             }
                         });
                         
                         // 设置相机距离
                         this.viewer.camera.setView({
                             destination: Cesium.Cartesian3.add(
                                 center,
                                 Cesium.Cartesian3.multiplyByScalar(
                                     Cesium.Cartesian3.normalize(center, new Cesium.Cartesian3()),
                                     radius * 2,
                                     new Cesium.Cartesian3()
                                 ),
                                 new Cesium.Cartesian3()
                             ),
                             orientation: {
                                 heading: 0.0,
                                 pitch: -Cesium.Math.PI_OVER_TWO,
                                 roll: 0.0
                             }
                         });
                         
                         console.log('手动定位成功');
                     }
                 }
                 
                 console.log('白膜3D Tiles加载成功');
                 this.status = '白膜3D Tiles加载成功！';
                 
                 // 存储引用
                 this.baimoTileset = baimoTileset;
                 
                 // 确保tileset可见
                 baimoTileset.show = true;
                 
                 // 设置调试选项
                 baimoTileset.debugShowBoundingVolume = true; // 显示边界框
                 baimoTileset.debugShowContentBoundingVolume = true; // 显示内容边界框
                 
                 // 监听加载事件
                 baimoTileset.tileLoad.addEventListener((tile) => this.onBaimoTileLoad(tile));
                 baimoTileset.tileFailed.addEventListener((tile, error) => this.onBaimoTileFailed(tile, error));
                 
                 // 强制刷新场景
                 this.viewer.scene.requestRender();
                 
             } catch (error) {
                 console.error('加载白膜3D Tiles失败:', error);
                 this.status = '加载白膜3D Tiles失败: ' + error.message;
             }
         },
         
         // 移除白膜3D Tiles
         removeBaimoTileset() {
             if (this.baimoTileset) {
                 this.viewer.scene.primitives.remove(this.baimoTileset);
                 this.baimoTileset = null;
                 this.status = '白膜3D Tiles已移除';
                 console.log('白膜3D Tiles已移除');
             }
         },
         
         // 切换白膜效果
         toggleBaimoWhiteMask() {
             if (!this.baimoTileset) {
                 this.status = '请先加载白膜3D Tiles';
                 return;
             }
             
             if (!this.baimoWhiteMaskActive) {
                 // 应用白膜效果 - 使用更自然的白色
                 this.baimoTileset.style = new Cesium.Cesium3DTileStyle({
                     color: {
                         conditions: [
                             [true, `color("white", ${this.baimoMaskOpacity})`]
                         ]
                     },
                     show: true
                 });
                 this.baimoWhiteMaskActive = true;
                 this.status = '白膜效果已启用';
                 console.log('白膜效果已启用');
             } else {
                 // 移除白膜效果，恢复原始颜色
                 this.baimoTileset.style = new Cesium.Cesium3DTileStyle({
                     color: {
                         conditions: [
                             [true, 'color("white", 1.0)'] // 保持白色但完全不透明
                         ]
                     },
                     show: true
                 });
                 this.baimoWhiteMaskActive = false;
                 this.status = '白膜效果已禁用，显示原始颜色';
                 console.log('白膜效果已禁用');
             }
         },
         
         // 调整白膜透明度
         adjustBaimoMaskOpacity(opacity) {
             this.baimoMaskOpacity = opacity;
             
             // 如果白膜效果已激活，重新应用
             if (this.baimoWhiteMaskActive && this.baimoTileset) {
                 this.baimoTileset.style = new Cesium.Cesium3DTileStyle({
                     color: {
                         conditions: [
                             [true, `color("white", ${opacity})`]
                         ]
                     }
                 });
             }
             
             this.status = `白膜透明度已调整为: ${Math.round(opacity * 100)}%`;
         },
         
         // 白膜瓦片加载成功事件
         onBaimoTileLoad(tile) {
             console.log('白膜瓦片加载成功:', tile);
         },
         
         // 白膜瓦片加载失败事件
         onBaimoTileFailed(tile, error) {
             console.error('白膜瓦片加载失败:', tile, error);
         },
         
         // 测试白膜3D Tiles连接
         testBaimoConnection() {
             const tilesetUrl = 'http://211.159.175.30:8011/baimo_tileset/2/tileset.json';
             
             fetch(tilesetUrl)
                 .then(response => {
                     if (response.ok) {
                         console.log('白膜服务器连接正常');
                         this.status = '白膜服务器连接正常';
                         return response.json();
                     } else {
                         throw new Error(`HTTP ${response.status}`);
                     }
                 })
                 .then(data => {
                     console.log('白膜tileset.json内容:', data);
                     this.status = '白膜tileset.json加载成功，包含 ' + (data.root?.children?.length || 0) + ' 个子模型';
                     
                     // 分析tileset数据
                     this.analyzeBaimoTileset(data);
                 })
                 .catch(error => {
                     console.error('白膜服务器连接失败:', error);
                     this.status = '白膜服务器连接失败: ' + error.message;
                 });
         },
         
         // 分析白膜tileset数据
         analyzeBaimoTileset(data) {
             console.log('=== 白膜Tileset数据分析 ===');
             
             if (data.root && data.root.boundingVolume) {
                 const bv = data.root.boundingVolume;
                 console.log('根节点边界体积:', bv);
                 
                 if (bv.box) {
                     // 解析box数据 [centerX, centerY, centerZ, axisX, axisY, axisZ, axisX, axisY, axisZ]
                     const box = bv.box;
                     console.log('边界框数据:', box);
                     
                     // 计算中心点
                     const center = [box[0], box[1], box[2]];
                     console.log('中心点坐标:', center);
                     
                     // 计算变换矩阵
                     if (data.root.transform) {
                         console.log('变换矩阵:', data.root.transform);
                     }
                 }
             }
             
             if (data.root && data.root.children) {
                 console.log('子节点数量:', data.root.children.length);
                 data.root.children.forEach((child, index) => {
                     console.log(`子节点${index}:`, {
                         content: child.content,
                         boundingVolume: child.boundingVolume,
                         geometricError: child.geometricError
                     });
                 });
             }
             
             console.log('=== 分析完成 ===');
         },
         
         // 调试白膜3D Tiles
         debugBaimoTileset() {
             if (!this.baimoTileset) {
                 this.status = '请先加载白膜3D Tiles';
                 return;
             }
             
             console.log('=== 白膜3D Tiles调试信息 ===');
             console.log('Tileset对象:', this.baimoTileset);
             console.log('是否可见:', this.baimoTileset.show);
             console.log('是否就绪:', this.baimoTileset.ready);
             console.log('边界球:', this.baimoTileset.boundingSphere);
             console.log('根节点:', this.baimoTileset.root);
             console.log('统计信息:', this.baimoTileset.statistics);
             console.log('样式:', this.baimoTileset.style);
             
             // 检查相机位置
             const camera = this.viewer.camera;
             console.log('相机位置:', camera.position);
             console.log('相机方向:', camera.direction);
             console.log('相机高度:', camera.positionCartographic ? camera.positionCartographic.height : 'N/A');
             
             // 显示白膜数据统计
             if (this.baimoTileset.statistics) {
                 const stats = this.baimoTileset.statistics;
                 console.log('=== 白膜数据统计 ===');
                 console.log('瓦片数量:', stats.numberOfTilesTotal);
                 console.log('可见瓦片:', stats.numberOfTilesWithContentReady);
                 console.log('几何体数量:', stats.numberOfTriangles);
                 console.log('纹理数量:', stats.numberOfTextures);
                 console.log('内存使用:', stats.geometryByteLength + stats.texturesByteLength, 'bytes');
                 
                 this.status = `白膜数据: ${stats.numberOfTilesTotal}瓦片, ${stats.numberOfTriangles}三角形, ${Math.round((stats.geometryByteLength + stats.texturesByteLength) / 1024)}KB`;
             } else {
                 this.status = '白膜3D Tiles调试信息已输出到控制台';
             }
         },
         
         // 强制定位到白膜数据
         forceLocateBaimo() {
             if (!this.baimoTileset) {
                 this.status = '请先加载白膜3D Tiles';
                 return;
             }
             
             try {
                 // 获取tileset的边界信息
                 const boundingSphere = this.baimoTileset.boundingSphere;
                 
                 if (boundingSphere) {
                     const center = boundingSphere.center;
                     const radius = boundingSphere.radius;
                     
                     console.log('强制定位到白膜数据:', {
                         center: center,
                         radius: radius
                     });
                     
                     // 计算相机位置（在边界球外部）
                     const cameraDistance = radius * 3; // 距离为半径的3倍
                     const cameraPosition = Cesium.Cartesian3.add(
                         center,
                         Cesium.Cartesian3.multiplyByScalar(
                             Cesium.Cartesian3.normalize(center, new Cesium.Cartesian3()),
                             cameraDistance,
                             new Cesium.Cartesian3()
                         ),
                         new Cesium.Cartesian3()
                     );
                     
                     // 设置相机位置
                     this.viewer.camera.setView({
                         destination: cameraPosition,
                         orientation: {
                             heading: 0.0,
                             pitch: -Cesium.Math.PI_OVER_TWO,
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已强制定位到白膜数据';
                     console.log('强制定位完成');
                 } else {
                     this.status = '无法获取白膜数据边界信息';
                 }
             } catch (error) {
                 console.error('强制定位失败:', error);
                 this.status = '强制定位失败: ' + error.message;
             }
         },
         
         // 切换到平面视图
         switchToTopView() {
             try {
                 console.log('切换到平面视图...');
                 
                 if (this.baimoTileset && this.baimoTileset.boundingSphere) {
                     // 如果有白膜数据，定位到白膜数据上方
                     const boundingSphere = this.baimoTileset.boundingSphere;
                     const center = boundingSphere.center;
                     const radius = boundingSphere.radius;
                     
                     // 计算相机位置（在白膜数据正上方）
                     const cameraHeight = radius * 5; // 高度为半径的5倍
                     const cameraPosition = Cesium.Cartesian3.add(
                         center,
                         new Cesium.Cartesian3(0, 0, cameraHeight),
                         new Cesium.Cartesian3()
                     );
                     
                     // 设置相机为俯视角度
                     this.viewer.camera.setView({
                         destination: cameraPosition,
                         orientation: {
                             heading: 0.0, // 正北方向
                             pitch: -Cesium.Math.PI_OVER_TWO, // 垂直向下
                             roll: 0.0 // 无旋转
                         }
                     });
                     
                     this.status = '已切换到白膜数据平面视图';
                     console.log('切换到白膜数据平面视图完成');
                 } else {
                     // 如果没有白膜数据，切换到默认平面视图
                     this.viewer.camera.setView({
                         destination: Cesium.Cartesian3.fromDegrees(120.16196180060605, 30.14332020097707, 1000000),
                         orientation: {
                             heading: 0.0,
                             pitch: -Cesium.Math.PI_OVER_TWO,
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到默认平面视图';
                     console.log('切换到默认平面视图完成');
                 }
                 
             } catch (error) {
                 console.error('切换到平面视图失败:', error);
                 this.status = '切换到平面视图失败: ' + error.message;
             }
         },
         
         // 切换到3D视图
         switchTo3DView() {
             try {
                 console.log('切换到3D视图...');
                 
                 if (this.baimoTileset && this.baimoTileset.boundingSphere) {
                     // 如果有白膜数据，定位到白膜数据侧方
                     const boundingSphere = this.baimoTileset.boundingSphere;
                     const center = boundingSphere.center;
                     const radius = boundingSphere.radius;
                     
                     // 计算相机位置（在白膜数据侧方）
                     const cameraDistance = radius * 4;
                     const cameraPosition = Cesium.Cartesian3.add(
                         center,
                         new Cesium.Cartesian3(cameraDistance, cameraDistance, cameraDistance),
                         new Cesium.Cartesian3()
                     );
                     
                     // 设置相机为3D角度
                     this.viewer.camera.setView({
                         destination: cameraPosition,
                         orientation: {
                             heading: Cesium.Math.toRadians(45), // 45度方向
                             pitch: Cesium.Math.toRadians(-30), // 30度俯视
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到白膜数据3D视图';
                     console.log('切换到白膜数据3D视图完成');
                 } else {
                     // 如果没有白膜数据，切换到默认3D视图
                     this.viewer.camera.setView({
                         destination: Cesium.Cartesian3.fromDegrees(120.16196180060605, 30.14332020097707, 500000),
                         orientation: {
                             heading: Cesium.Math.toRadians(45),
                             pitch: Cesium.Math.toRadians(-30),
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到默认3D视图';
                     // console.log('切换到默认3D视图完成');
                 }
                 
             } catch (error) {
                 // console.error('切换到3D视图失败:', error);
                 this.status = '切换到3D视图失败: ' + error.message;
             }
         },
         
         // 切换到垂直视图（侧面视角）
         switchToVerticalView() {
             try {
                 // console.log('切换到垂直视图...');
                 
                 if (this.baimoTileset && this.baimoTileset.boundingSphere) {
                     // 如果有白膜数据，定位到白膜数据侧面
                     const boundingSphere = this.baimoTileset.boundingSphere;
                     const center = boundingSphere.center;
                     const radius = boundingSphere.radius;
                     
                     // 计算相机位置（在白膜数据侧面，水平视角）
                     const cameraDistance = radius * 3;
                     const cameraPosition = Cesium.Cartesian3.add(
                         center,
                         new Cesium.Cartesian3(cameraDistance, 0, 0), // 在X轴正方向
                         new Cesium.Cartesian3()
                     );
                     
                     // 设置相机为水平视角（垂直观察）
                     this.viewer.camera.setView({
                         destination: cameraPosition,
                         orientation: {
                             heading: Cesium.Math.toRadians(90), // 向西看（90度）
                             pitch: 0.0, // 水平视角
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到白膜数据垂直视图（侧面）';
                     // console.log('切换到白膜数据垂直视图完成');
                 } else {
                     // 如果没有白膜数据，切换到默认垂直视图
                     this.viewer.camera.setView({
                         destination: Cesium.Cartesian3.fromDegrees(120.16196180060605, 30.14332020097707, 1000),
                         orientation: {
                             heading: Cesium.Math.toRadians(90),
                             pitch: 0.0,
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到默认垂直视图';
                     // console.log('切换到默认垂直视图完成');
                 }
                 
             } catch (error) {
                 // console.error('切换到垂直视图失败:', error);
                 this.status = '切换到垂直视图失败: ' + error.message;
             }
         },
         
         // 切换到垂直视图（北向视角）
         switchToNorthView() {
             try {
                 // console.log('切换到北向垂直视图...');
                 
                 if (this.baimoTileset && this.baimoTileset.boundingSphere) {
                     // 如果有白膜数据，定位到白膜数据北面
                     const boundingSphere = this.baimoTileset.boundingSphere;
                     const center = boundingSphere.center;
                     const radius = boundingSphere.radius;
                     
                     // 计算相机位置（在白膜数据北面，向南看）
                     const cameraDistance = radius * 3;
                     const cameraPosition = Cesium.Cartesian3.add(
                         center,
                         new Cesium.Cartesian3(0, cameraDistance, 0), // 在Y轴正方向（北）
                         new Cesium.Cartesian3()
                     );
                     
                     // 设置相机为水平视角（向南看）
                     this.viewer.camera.setView({
                         destination: cameraPosition,
                         orientation: {
                             heading: Cesium.Math.toRadians(180), // 向南看（180度）
                             pitch: 0.0, // 水平视角
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到白膜数据北向垂直视图';
                     // console.log('切换到白膜数据北向垂直视图完成');
                 } else {
                     // 如果没有白膜数据，切换到默认北向视图
                     this.viewer.camera.setView({
                         destination: Cesium.Cartesian3.fromDegrees(120.16196180060605, 30.14332020097707, 1000),
                         orientation: {
                             heading: Cesium.Math.toRadians(180),
                             pitch: 0.0,
                             roll: 0.0
                         }
                     });
                     
                     this.status = '已切换到默认北向垂直视图';
                     // console.log('切换到默认北向垂直视图完成');
                 }
                 
             } catch (error) {
                 // console.error('切换到北向垂直视图失败:', error);
                 this.status = '切换到北向垂直视图失败: ' + error.message;
             }
         },
         
         // 显示当前视角信息
         showCurrentViewInfo() {
             try {
                 const camera = this.viewer.camera;
                 const position = camera.position;
                 const orientation = camera.heading;
                 const pitch = camera.pitch;
                 const roll = camera.roll;
                 
                 // 转换为地理坐标
                 const cartographic = Cesium.Cartographic.fromCartesian(position);
                 const longitude = Cesium.Math.toDegrees(cartographic.longitude);
                 const latitude = Cesium.Math.toDegrees(cartographic.latitude);
                 const height = cartographic.height;
                 
                 // 转换为角度
                 const headingDegrees = Cesium.Math.toDegrees(orientation);
                 const pitchDegrees = Cesium.Math.toDegrees(pitch);
                 const rollDegrees = Cesium.Math.toDegrees(roll);
                 
                 // console.log('=== 当前视角信息 ===');
                 // console.log('相机位置:', {
                 //     经度: longitude.toFixed(6),
                 //     纬度: latitude.toFixed(6),
                 //     高度: Math.round(height) + '米'
                 // });
                 // console.log('相机方向:', {
                 //     航向: headingDegrees.toFixed(1) + '°',
                 //     俯仰: pitchDegrees.toFixed(1) + '°',
                 //     翻滚: rollDegrees.toFixed(1) + '°'
                 // });
                 
                 // 判断当前视角类型
                 let viewType = '未知';
                 if (Math.abs(pitchDegrees) < 5) {
                     viewType = '水平视角';
                 } else if (Math.abs(pitchDegrees) > 85) {
                     viewType = '垂直俯视';
                 } else if (pitchDegrees < -30) {
                     viewType = '3D俯视';
                 } else {
                     viewType = '3D仰视';
                 }
                 
                 this.status = `当前视角: ${viewType} | 位置: ${longitude.toFixed(4)}, ${latitude.toFixed(4)} | 高度: ${Math.round(height)}m | 航向: ${headingDegrees.toFixed(0)}°`;
                 
             } catch (error) {
                 console.error('获取视角信息失败:', error);
                 this.status = '获取视角信息失败';
             }
         },
         
         // 创建测试建筑物（简单立方体）
         createTestBuilding() {
             try {
                 console.log('创建测试建筑物...');
                 
                 // 创建一个简单的立方体作为测试建筑物
                 const building = this.viewer.entities.add({
                     position: Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 100), // 北京坐标
                     box: {
                         dimensions: new Cesium.Cartesian3(100, 100, 200), // 长宽高
                         material: Cesium.Color.BLUE.withAlpha(0.8),
                         outline: true,
                         outlineColor: Cesium.Color.BLACK
                     }
                 });
                 
                 // 定位到建筑物
                 this.viewer.zoomTo(building);
                 this.status = '已创建测试建筑物';
                 console.log('测试建筑物创建完成');
                 
             } catch (error) {
                 console.error('创建测试建筑物失败:', error);
                 this.status = '创建测试建筑物失败';
             }
         },
         
         // 调试：检查当前场景中的3D Tiles图层
         debug3DTiles() {
             console.log('=== 调试3D Tiles图层 ===');
             
             const primitives = this.viewer.scene.primitives._primitives;
             console.log('场景中的图元总数:', primitives.length);
             
             const tilesets = primitives.filter(primitive => 
                 primitive instanceof Cesium.Cesium3DTileset
             );
             
             console.log('3D Tiles图层数量:', tilesets.length);
             
             tilesets.forEach((tileset, index) => {
                 console.log(`图层${index + 1}:`, {
                     类型: tileset.constructor.name,
                     URL: tileset.url,
                     是否就绪: tileset.ready,
                     样式: tileset.style ? '已设置' : '未设置',
                     是否为白膜: tileset === this.baimoTileset ? '是' : '否'
                 });
             });
             
             // 显示白膜3D Tiles状态
             if (this.baimoTileset) {
                 console.log('白膜3D Tiles状态:', {
                     已加载: !!this.baimoTileset,
                     白膜效果: this.baimoWhiteMaskActive ? '已启用' : '已禁用',
                     透明度: this.baimoMaskOpacity
                 });
             }
             
             this.status = `找到 ${tilesets.length} 个3D Tiles图层${this.baimoTileset ? ', 包含白膜3D Tiles' : ''}`;
         },
         
         // 测试消息记录功能
         testMessageLog() {
             const now = Math.floor(Date.now() / 1000); // 当前秒级时间戳
             const testMessages = [
                 { action: 1, remark: '测试返航消息（当前时间）', time: now },
                 { action: 2, remark: '测试自爆消息（1分钟前）', time: now - 60 },
                 { action: 3, remark: '测试迫降消息（2分钟前）', time: now - 120 },
                 { action: 4, remark: '测试继续飞行消息（5分钟前）', time: now - 300 },
                 { action: 5, remark: '测试避障碍物消息（10分钟前）', time: now - 600 },
                 { action: 6, remark: '测试业务操作消息（1小时前）', time: now - 3600 }
             ];
             
             testMessages.forEach(msg => {
                 this.processMessageLog(msg);
             });
             
             this.status = `已添加测试消息记录（秒级时间戳：${now}）`;
         },
         
         // 调试时间信息
         debugTimeInfo() {
             const now = Math.floor(Date.now() / 1000); // 当前秒级时间戳
             const testCases = [
                 now, // 当前秒级时间戳
                 now - 60, // 1分钟前
                 now - 3600, // 1小时前
                 now - 86400, // 1天前
                 String(now), // 字符串格式的秒级时间戳
                 Date.now(), // 毫秒级时间戳
                 '2024-01-01T12:00:00Z', // ISO字符串
                 '2024-01-01 12:00:00', // 普通字符串
                 null, // 空值
                 undefined, // 未定义
                 '', // 空字符串
                 'invalid' // 无效值
             ];
             
             let debugInfo = '秒级时间戳处理测试:\n\n';
             
             testCases.forEach((testCase, index) => {
                 const displayValue = this.formatTime(testCase);
                 debugInfo += `测试${index + 1}: ${JSON.stringify(testCase)}\n`;
                 debugInfo += `  原始类型: ${typeof testCase}\n`;
                 debugInfo += `  显示结果: ${displayValue}\n\n`;
             });
             
             alert(debugInfo);
         },
         
         // 专门测试秒级时间戳
         testSecondTimestamp() {
             // 模拟WebSocket返回的秒级时间戳消息
             const wsMessages = [
                 { action: 1, remark: 'WebSocket返航消息', time: 1704067200 },
                 { action: 2, remark: 'WebSocket自爆消息', time: 1704067170 }, // 30秒前
                 { action: 3, remark: 'WebSocket迫降消息', time: 1704067080 }, // 2分钟前
                 { action: 4, remark: 'WebSocket继续飞行消息', time: 1704066600 }, // 10分钟前
                 { action: 5, remark: 'WebSocket避障碍物消息', time: 1704063600 }, // 1小时前
                 { action: 6, remark: 'WebSocket业务操作消息', time: 1703980800 } // 1天前
             ];
             
             // 清空现有记录
             this.messageLogs = [];
             
             // 添加测试消息
             wsMessages.forEach(msg => {
                 this.processMessageLog(msg);
             });
             
             this.status = `已添加秒级时间戳测试消息，直接显示原始时间戳`;
             
             console.log('秒级时间戳测试:', {
                 消息数量: wsMessages.length,
                 时间戳示例: wsMessages[0].time
             });
         },
         
         // 测试formatTime方法
         testFormatTime() {
             const testCases = [
                 1756011918, // 你提到的时间戳
                 Math.floor(Date.now() / 1000), // 当前秒级时间戳
                 Date.now(), // 当前毫秒级时间戳
                 '1756011918', // 字符串格式
                 '2024-01-01 12:00:00' // 时间字符串
             ];
             
             let result = 'formatTime 方法测试结果:\n\n';
             
             testCases.forEach((testCase, index) => {
                 const formatted = this.formatTime(testCase);
                 result += `测试${index + 1}: ${JSON.stringify(testCase)}\n`;
                 result += `  格式化结果: ${formatted}\n\n`;
             });
             
             alert(result);
         },
         
         // 强制刷新页面
         forceRefresh() {
             if (confirm('确定要强制刷新页面吗？这将重新加载所有代码。')) {
                 window.location.reload(true);
             }
         },
         
         // 显示时间处理说明
         showTimeHelp() {
             const helpText = `实时消息时间处理说明：

1. 秒级时间戳处理：
   • WebSocket返回秒级时间戳（如：1704067200）
   • 系统自动识别并转换为可读时间格式
   • 显示格式：YYYY-MM-DD HH:mm:ss

2. 支持的时间格式：
   • 秒级时间戳（数字）：1704067200 → 2024-01-01 12:00:00
   • 秒级时间戳（字符串）：'1704067200' → 2024-01-01 12:00:00
   • 毫秒级时间戳：1704067200000 → 2024-01-01 12:00:00
   • 时间字符串：'2024-01-01 12:00:00' → 2024-01-01 12:00:00
   • ISO格式：'2024-01-01T12:00:00Z' → 2024-01-01 12:00:00

3. 自动识别逻辑：
   • 数字 < 10000000000 → 秒级时间戳 → 乘以1000转换
   • 数字 >= 10000000000 → 毫秒级时间戳 → 直接转换
   • 字符串纯数字10位 → 秒级时间戳 → 乘以1000转换
   • 其他字符串 → 尝试直接解析

4. 测试功能：
   • "测试"：使用当前秒级时间戳
   • "秒级测试"：使用固定秒级时间戳
   • "时间调试"：测试各种时间格式

5. 解决显示问题：
   • 修复了秒级时间戳显示为"487780:53:18"的问题
   • 现在正确显示为"2024-01-01 12:00:00"格式

6. 调试功能：
   • 添加了控制台日志输出
   • 可以查看formatTime方法的处理过程
   • "强制刷新"按钮可以重新加载最新代码`;

             alert(helpText);
         },
        
                 processRouteData(routeData) {
             // 处理航线数据
             // console.log('收到航线信息:', routeData);
             
             try {
                 // 根据航线数据格式进行处理
                 if (Array.isArray(routeData)) {
                     // 如果是数组格式，处理多条航线
                     // console.log(`处理${routeData.length}条航线`);
                     routeData.forEach((route, index) => {
                         // console.log(`处理航线${index}:`, route);
                         this.createRouteOnMap(route, index);
                     });
                 } else {
                     // 如果是单个航线对象
                     // console.log('处理单条航线:', routeData);
                     this.createRouteOnMap(routeData, 0);
                 }
                 
                 this.status = `已加载航线信息，共${Array.isArray(routeData) ? routeData.length : 1}条航线`;
             } catch (error) {
                 console.error('处理航线数据失败:', error);
                 this.status = '处理航线数据失败';
             }
         },
         
         // 处理起降场数据
         processLandingFieldData(landingFieldData) {
             // 收到起降场信息
             
             try {
                 if (Array.isArray(landingFieldData)) {
                     // 清除之前的起降场实体
                     this.clearLandingFieldEntities();
                     
                     // 处理每个起降场
                     landingFieldData.forEach((field, index) => {
                         this.createLandingFieldEntity(field, index);
                     });
                     
                     // 强制刷新起降场显示
                     this.refreshLandingFieldDisplay();
                     
                     // 已加载起降场
                     this.status = `已加载起降场信息，共${landingFieldData.length}个起降场`;
                 } else {
                     console.warn('起降场数据格式错误，应为数组:', landingFieldData);
                     this.status = '起降场数据格式错误';
                 }
             } catch (error) {
                 console.error('处理起降场数据失败:', error);
                 this.status = '处理起降场数据失败';
             }
         },
         
         // 创建起降场实体
         createLandingFieldEntity(field, index) {
             try {
                 // 解析经纬度
                 const locationParts = field.location.split(',');
                 if (locationParts.length !== 2) {
                     console.warn(`起降场${index}坐标格式错误:`, field.location);
                     return;
                 }
                 
                 const longitude = parseFloat(locationParts[0]);
                 const latitude = parseFloat(locationParts[1]);
                 
                 if (isNaN(longitude) || isNaN(latitude)) {
                     console.warn(`起降场${index}坐标解析失败:`, field.location);
                     return;
                 }
                 
                 // 创建起降场实体
                 const entity = this.viewer.entities.add({
                     position: Cesium.Cartesian3.fromDegrees(longitude, latitude),
                     point: {
                         pixelSize: 20, // 增大点的大小，让起降场更明显
                         color: Cesium.Color.ORANGE,
                         outlineColor: Cesium.Color.WHITE,
                         outlineWidth: 3,
                         zIndex: 300, // 设置最高图层顺序，确保起降场在最上层
                         distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE), // 在任何距离都显示
                         show: true // 确保可见
                     },
                     label: {
                         text: field.locationName,
                         font: '14pt sans-serif', // 增大字体
                         style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                         outlineWidth: 3,
                         verticalOrigin: Cesium.VerticalOrigin.TOP,
                         pixelOffset: new Cesium.Cartesian2(0, 25),
                         fillColor: Cesium.Color.ORANGE,
                         outlineColor: Cesium.Color.WHITE,
                         zIndex: 300, // 设置最高图层顺序
                         distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE), // 在任何距离都显示
                         show: this.showLandingFieldNames, // 根据设置控制显示
                         disableDepthTestDistance: Number.POSITIVE_INFINITY // 禁用深度测试，确保标签始终显示在最前面
                     }
                 });
                 
                 // 起降场实体创建完成
                 
                 // 存储实体引用和原始数据
                 if (!this.landingFieldEntities) {
                     this.landingFieldEntities = {};
                 }
                 this.landingFieldEntities[field.id] = {
                     entity: entity,
                     data: field
                 };
                 
                 // console.log(`起降场 ${field.siteName} (ID: ${field.id}) 已添加到地图`);
                 
                 // console.log(`已创建起降场${index + 1}: ${field.siteName} (${longitude}, ${latitude})`);
                 
             } catch (error) {
                 console.error(`创建起降场实体失败:`, error);
             }
         },
         
         // 显示起降场详情对话框
         showLandingFieldDialog(fieldData) {
             try {
                 // 解析extraAttributes
                 let extraAttributes = {};
                 if (fieldData.extraAttributes) {
                     try {
                         extraAttributes = JSON.parse(fieldData.extraAttributes);
                     } catch (e) {
                         console.warn('解析extraAttributes失败:', e);
                         extraAttributes = { '原始数据': fieldData.extraAttributes };
                     }
                 }
                 
                 // 显示对话框
                 this.showEditDialog(fieldData.locationName, extraAttributes, fieldData);
                 
             } catch (error) {
                 console.error('显示起降场对话框失败:', error);
             }
         },
         
         // 清除起降场实体
         clearLandingFieldEntities() {
             if (this.landingFieldEntities) {
                 Object.values(this.landingFieldEntities).forEach(item => {
                     this.viewer.entities.remove(item.entity);
                 });
                 this.landingFieldEntities = {};
             }
         },
         
         // 强制刷新起降场显示
         refreshLandingFieldDisplay() {
             if (this.landingFieldEntities) {
                 Object.values(this.landingFieldEntities).forEach(item => {
                     if (item.entity && item.entity.point) {
                         // 强制刷新点的显示
                         item.entity.point.show = true;
                         item.entity.point.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE);
                     }
                     if (item.entity && item.entity.label) {
                         // 根据设置控制标签的显示
                         item.entity.label.show = this.showLandingFieldNames;
                         item.entity.label.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, Number.MAX_VALUE);
                         item.entity.label.disableDepthTestDistance = Number.POSITIVE_INFINITY;
                     }
                 });
             }
         },
         
         // 切换起降场名称显示状态
         toggleLandingFieldNames() {
             this.showLandingFieldNames = !this.showLandingFieldNames;
             
             // 刷新起降场显示
             this.refreshLandingFieldDisplay();
             
             // 更新状态信息
             this.status = this.showLandingFieldNames ? '已显示起降场名称' : '已隐藏起降场名称';
             
             console.log(`起降场名称显示状态已切换为: ${this.showLandingFieldNames ? '显示' : '隐藏'}`);
         },
         
         // 添加全局点击事件处理器
         addGlobalClickHandler() {
             if (!this.viewer) return;
             
             // 创建全局点击事件处理器
             this.globalClickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
             
             this.globalClickHandler.setInputAction((click) => {
                 // console.log('点击事件触发');
                 const pickedObject = this.viewer.scene.pick(click.position);
                 // console.log('点击的对象:', pickedObject);
                 
                 if (pickedObject && pickedObject.id) {
                     // console.log('点击的实体ID:', pickedObject.id);
                     
                     // 检查是否是飞机实体
                     const entityId = pickedObject.id.id || pickedObject.id;
                     if (typeof entityId === 'string' && entityId.startsWith('aircraft-')) {
                         const trackId = entityId.replace('aircraft-', '');
                         console.log('点击了飞机实体:', trackId);
                         
                         // 设置为当前选中的轨迹
                         this.setCurrentTrack(trackId);
                         
                         // 查找对应的任务
                         const task = this.taskList.find(task => task.uuid === trackId);
                         if (task) {
                             // 清除选中任务缓存，确保状态更新
                             this.clearSelectedTaskCache();
                             
                             // 设置selectedTrackId会触发watcher，自动调用goToTaskPage
                             this.selectedTrackId = trackId;
                             
                             // 查找任务在排序后列表中的位置
                             const sortedTasks = this.sortedTaskList;
                             const taskIndex = sortedTasks.findIndex(t => t.uuid === trackId);
                             if (taskIndex !== -1) {
                                 // 计算任务所在的页码
                                 const page = Math.floor(taskIndex / this.pageSize) + 1;
                                 // 设置当前页码
                                 this.currentPage = page;
                                 console.log(`找到对应任务，位于第${page}页，索引${taskIndex}，已高亮显示`);
                             }
                         }
                         
                         return;
                     }
                     
                     // 检查是否是起降场实体
                     if (this.landingFieldEntities) {
                         // console.log('当前起降场实体数量:', Object.keys(this.landingFieldEntities).length);
                         Object.values(this.landingFieldEntities).forEach(item => {
                             // console.log('检查实体:', item.entity, '是否匹配:', item.entity === pickedObject.id);
                             if (item.entity === pickedObject.id) {
                                 // console.log('点击了起降场:', item.data.siteName);
                                 this.showLandingFieldDialog(item.data);
                                 return;
                             }
                         });
                     }
                 }
             }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
             
             console.log('已添加全局点击事件处理器（支持点击飞机高亮任务）');
         },
         
         // 显示编辑对话框
         showEditDialog(title, extraAttributes, originalData) {
             this.currentEditTitle = title;
             this.currentEditData = originalData;
             this.editedExtraAttributes = JSON.parse(JSON.stringify(extraAttributes)); // 深拷贝
             this.showEditDialogFlag = true;
         },
         
         // 关闭编辑对话框
         closeEditDialog() {
             this.showEditDialogFlag = false;
             this.currentEditData = null;
             this.currentEditTitle = '';
             this.editedExtraAttributes = {};
         },
         
         // 保存编辑对话框
         saveEditDialog() {
             try {
                 // 更新原始数据
                 if (this.currentEditData) {
                     this.currentEditData.extraAttributes = JSON.stringify(this.editedExtraAttributes);
                     // console.log('已更新起降场数据:', this.currentEditData);
                     
                     // 这里可以添加向服务器发送更新请求的逻辑
                     // this.updateLandingFieldData(this.currentEditData);
                 }
                 
                 this.closeEditDialog();
                 this.status = '起降场数据已更新';
                 
             } catch (error) {
                 console.error('保存编辑数据失败:', error);
                 this.status = '保存编辑数据失败';
             }
         },
         
         // 任务关联功能已恢复
         
         // 检查任务是否完成
         checkTaskCompletion(trackId, currentPoint) {
             // 性能监控：记录开始时间
             const startTime = performance.now();
             
             // 查找对应的任务
             const task = this.taskList.find(task => task.uuid === trackId);
             if (!task || !this.taskStatus[task.uuid]) return;
             
             const taskStatus = this.taskStatus[task.uuid];
             if (taskStatus.completed) return; // 任务已完成
             
             // 检查是否到达终点起降场
             if (task.destinationId && this.landingFieldEntities[task.destinationId]) {
                 const destinationField = this.landingFieldEntities[task.destinationId].data;
                 const destinationLocation = destinationField.location.split(',');
                 const destLng = parseFloat(destinationLocation[0]);
                 const destLat = parseFloat(destinationLocation[1]);
                 
                 // 计算距离（简单欧几里得距离，实际应用中可能需要更精确的计算）
                 const distance = Math.sqrt(
                     Math.pow(currentPoint.longitude - destLng, 2) + 
                     Math.pow(currentPoint.latitude - destLat, 2)
                 );
                 
                 // 如果距离小于阈值（约100米），认为到达终点
                 const threshold = 0.001; // 约100米
                 if (distance < threshold) {
                     this.completeTask(task.uuid);
                 }
             }
             
             // 性能监控：记录执行时间
             const endTime = performance.now();
             const executionTime = endTime - startTime;
             
             // 更新性能统计
             this.taskCompletionStats.totalChecks++;
             this.taskCompletionStats.totalTime += executionTime;
             this.taskCompletionStats.avgTime = this.taskCompletionStats.totalTime / this.taskCompletionStats.totalChecks;
             
             // 如果执行时间超过1ms，记录警告
             if (executionTime > 1) {
                 console.warn(`任务完成检查耗时过长: ${executionTime.toFixed(2)}ms, trackId: ${trackId}`);
             }
         },
         
         // 完成任务
         completeTask(taskUuid) {
             const taskStatus = this.taskStatus[taskUuid];
             if (!taskStatus || taskStatus.completed) return;
             
             taskStatus.completed = true;
             
             // 隐藏飞机实体
             if (taskStatus.aircraftEntity) {
                 taskStatus.aircraftEntity.show = false;
                 console.log(`✅ 任务 ${taskUuid} 完成，已隐藏飞机图标`);
             }
             
             // 更新状态
             const task = this.taskList.find(t => t.uuid === taskUuid);
             if (task) {
                 this.status = `任务 "${task.name}" 已完成，飞机图标已隐藏`;
             }
             
             // 记录任务完成统计
             const completedTasks = Object.values(this.taskStatus).filter(status => status.completed).length;
             const totalTasks = this.taskList.length;
             console.log(`📊 任务完成进度: ${completedTasks}/${totalTasks} (${((completedTasks/totalTasks)*100).toFixed(1)}%)`);
         },
         
         // 处理任务列表数据
         processTaskListData(taskData) {
             
             
             try {
                 if (Array.isArray(taskData)) {
     
                     this.taskList = taskData;
                     
                     // 初始化任务状态跟踪
                     taskData.forEach((task, index) => {
                         console.log(`任务${index + 1}:`, {
                             uuid: task.uuid,
                             name: task.name,
                             aircraftType: task.aircraftType
                         });
                         
                         if (task.uuid && !this.taskStatus[task.uuid]) {
                             this.taskStatus[task.uuid] = {
                                 completed: false,
                                 aircraftEntity: null,
                                 originId: task.originId,
                                 destinationId: task.destinationId
                             };
                         }
                     });
                     
                     // 移除任务名称缓存清理，性能优先
                     // 移除标签更新，性能优先
                     
                     // 重置请求状态
                     this.isRequestingTasks = false;
                     console.log(`✅ 重置请求状态: ${this.isRequestingTasks}`);
                     
                     console.log(`✅ 已加载${taskData.length}个任务`);
                     console.log('📋 任务列表uuid:', taskData.map(t => t.uuid));
                     this.status = `已加载任务列表，共${taskData.length}个任务`;
                     
                     // 只有当任务列表数据大于0时，才开始实时渲染轨迹点数据
                     if (taskData.length > 0) {
                         console.log('任务列表数据大于0，开始实时渲染轨迹点数据');
                         this.initRealTimeRendering();
                     } else {
                         console.log('任务列表为空，不启动实时渲染');
                     }
                 } else {
                     console.warn('任务数据格式错误，应为数组:', taskData);
                     this.status = '任务数据格式错误';
                 }
             } catch (error) {
                 console.error('处理任务列表数据失败:', error);
                 this.status = '处理任务列表数据失败';
             }
         },
         
         createRouteOnMap(route, index) {
             // 在地图上创建航线
             try {
                 // console.log(`开始创建航线${index}:`, route);
                 
                 // 根据航线数据格式创建航线实体
                 // 航线数据格式和轨迹数据类似，包含pts数组
                 if (route.pts && Array.isArray(route.pts)) {
                     // console.log(`航线${index}使用pts格式，共${route.pts.length}个点`);
                     // 创建航线路径
                     const positions = [];
                     route.pts.forEach((point, pointIndex) => {
                         if (point.lng && point.lat) {
                             positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.alt || 100));
                             // console.log(`航线${index}点${pointIndex}: ${point.lng}, ${point.lat}, ${point.alt || 100}`);
                         } else {
                             console.warn(`航线${index}点${pointIndex}坐标无效:`, point);
                         }
                     });
                     
                     // console.log(`航线${index}有效位置数量:`, positions.length);
                     
                     if (positions.length >= 2) {
                         // 创建航线实体
                         const routeEntity = this.viewer.entities.add({
                             polyline: {
                                 positions: positions,
                                 width: 6,
                                 material: Cesium.Color.BLUE.withAlpha(1.0), // 使用蓝色区分航线
                                 clampToGround: false,
                                 zIndex: 50 // 设置图层顺序，确保航线在轨迹线下方
                             }
                         });
                         
                         // 存储航线实体引用
                         if (!this.routeEntities) {
                             this.routeEntities = {};
                         }
                         this.routeEntities[`route_${index}`] = routeEntity;
                         
                         // console.log(`已创建航线${index + 1}: ${route.aircraftType || '航线'}${index + 1} (${route.missionType || ''})`);
                         // console.log('航线实体:', routeEntity);
                         
                         // 检查实体是否成功添加到viewer
                         // console.log('当前viewer实体数量:', this.viewer.entities.values.length);
                     }
                 } else if (route.points && Array.isArray(route.points)) {
                     // 兼容旧格式
                     // console.log(`航线${index}使用points格式，共${route.points.length}个点`);
                     const positions = [];
                     route.points.forEach((point, pointIndex) => {
                         if (point.lng && point.lat) {
                             positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.alt || 100));
                         }
                     });
                     
                     if (positions.length >= 2) {
                         const routeEntity = this.viewer.entities.add({
                             polyline: {
                                 positions: positions,
                                 width: 6,
                                 material: Cesium.Color.BLUE.withAlpha(1.0),
                                 clampToGround: false
                             }
                         });
                         
                         if (!this.routeEntities) {
                             this.routeEntities = {};
                         }
                         this.routeEntities[`route_${index}`] = routeEntity;
                         
                         // console.log(`已创建航线${index + 1}:`, route.name || `航线${index + 1}`);
                     }
                 } else if (route.coordinates && Array.isArray(route.coordinates)) {
                     // 兼容GeoJSON格式
                     // console.log(`航线${index}使用coordinates格式，共${route.coordinates.length}个坐标`);
                     const positions = [];
                     route.coordinates.forEach((coord, coordIndex) => {
                         if (coord.length >= 2) {
                             positions.push(Cesium.Cartesian3.fromDegrees(coord[0], coord[1], coord[2] || 100));
                         }
                     });
                     
                     if (positions.length >= 2) {
                         const routeEntity = this.viewer.entities.add({
                             polyline: {
                                 positions: positions,
                                 width: 6,
                                 material: Cesium.Color.BLUE.withAlpha(1.0),
                                 clampToGround: false,
                                 zIndex: 50 // 设置图层顺序，确保航线在轨迹线下方
                             }
                         });
                         
                         if (!this.routeEntities) {
                             this.routeEntities = {};
                         }
                         this.routeEntities[`route_${index}`] = routeEntity;
                         
                         // console.log(`已创建航线${index + 1}:`, route.name || `航线${index + 1}`);
                     }
                 }
             } catch (error) {
                 console.error('创建航线失败:', error);
             }
         },
         
         processTrackData(trackList) {
             // 处理轨迹数据
             
             // 如果是第一次收到轨迹数据，获取第一个轨迹的pid作为方案ID
             if (this.flightTracks.length === 0 && trackList && trackList.length > 0 && trackList[0] && trackList[0].pid) {
                 const firstTrackPid = trackList[0].pid;
                 this.planId = firstTrackPid.toString();
                 this.batchPlanId = firstTrackPid;
                 this.status = `已从轨迹数据获取方案ID: ${firstTrackPid}`;
                 
                 // 不再自动获取航线，需要用户手动点击获取航线按钮
             }
             
             if (trackList && Array.isArray(trackList)) {
                 trackList.forEach((trackData, index) => {
                const trackId = trackData.tid;
                const color = this.trackColors[index % this.trackColors.length];
                
                // 转换数据格式 - 兼容新旧格式，并过滤无效数据
                const points = (trackData.pts || [])
                    .filter(pt => pt && 
                        typeof pt.lng === 'number' && !isNaN(pt.lng) &&
                        typeof pt.lat === 'number' && !isNaN(pt.lat) &&
                        typeof pt.alt === 'number' && !isNaN(pt.alt) &&
                        pt.lng >= -180 && pt.lng <= 180 &&
                        pt.lat >= -90 && pt.lat <= 90)
                    .map((pt, ptIndex) => ({
                        longitude: pt.lng,
                        latitude: pt.lat,
                        altitude: pt.alt,
                        speed: pt.spd,
                        timestamp: pt.ts - trackData.startTime, // 相对时间戳
                        name: `轨迹${index + 1}点${ptIndex}`,
                        // 新增字段
                        battery: pt.batt,
                        timestamp_absolute: pt.ts
                    }));
                
                // 如果过滤后没有有效点，跳过这条轨迹
                if (points.length === 0) {
                    return;
                }
                
                // 更新或创建轨迹
                const trackDataToUpdate = {
                    id: trackId,
                    color: color,
                    points: points,
                    startTime: trackData.startTime,
                    endTime: trackData.endTime,
                    duration: trackData.dur,
                    distance: trackData.dist,
                    // 新增字段
                    aircraft_type: trackData.aircraft_type,
                    mission_type: trackData.mission_type,
                    esId: trackData.esId,
                    pid: trackData.pid,
                    tid: trackData.tid, // 添加tid字段
                    relId: trackData.relId,
                    schema_requirement_id: trackData.schema_requirement_id,
                    sid: trackData.sid,
                    spId: trackData.spId,
                    typeId: trackData.typeId,
                    vid: trackData.vid
                };
                
                this.updateTrack(trackId, trackDataToUpdate);
                });
            }
            
            const aircraftTypes = trackList ? [...new Set(trackList.map(t => t.aircraft_type).filter(Boolean))] : [];
            const typeInfo = aircraftTypes.length > 0 ? ` (${aircraftTypes.join(', ')})` : '';
            const totalPoints = this.flightTracks.reduce((sum, track) => 
                sum + (track && track.points ? track.points.length : 0), 0
            );
            this.status = `已接收${trackList ? trackList.length : 0}条轨迹数据${typeInfo}，累计${totalPoints}个轨迹点，实时渲染中...`;
            
            // 如果是首次加载轨迹数据，定位到第一条轨迹的第一个点，并选中第一个轨迹
            if (this.flightTracks.length === (trackList ? trackList.length : 0) && trackList && trackList.length > 0) {
                // 延迟一点时间确保轨迹实体已创建完成
                setTimeout(() => {
                    this.focusToFirstTrackPoint();
                    // 自动选中第一个轨迹
                    this.setCurrentTrack(0);
                }, 500);
            }
            
            // 重新应用建筑物白膜（如果之前已激活）
            if (this.buildingMaskActive) {
                setTimeout(() => {
                    this.reapplyBuildingWhiteMask();
                }, 1000); // 延迟1秒确保轨迹渲染完成
            }
        },
        
        updateTrack(trackId, trackData) {
            // 安全检查：确保参数有效
            if (!trackId || !trackData) {
                // console.warn('updateTrack: 参数无效', { trackId, trackData });
                return;
            }
            
            // 安全检查：确保flightTracks存在
            if (!this.flightTracks || !Array.isArray(this.flightTracks)) {
                this.flightTracks = [];
            }
            
            // 如果轨迹不存在，创建新的
            if (!this.flightTracks.find(t => t && t.id === trackId)) {
                this.flightTracks.push(trackData);
                
                // 创建轨迹线
                this.createTrackPolyline(trackId, trackData);
                
                // 创建飞机实体
                this.createAircraftEntity(trackId, trackData);
                
                // 如果是第一条轨迹，设置相机位置并选中
                if (this.flightTracks.length === 1) {
                    this.focusFirstPoint();
                    // 自动选中第一个轨迹
                    this.setCurrentTrack(0);
                }
                
                // 移除标签更新调用，性能优先
            } else {
                // 更新现有轨迹 - 累积轨迹点而不是替换
                const trackIndex = this.flightTracks.findIndex(t => t.id === trackId);
                const existingTrack = this.flightTracks[trackIndex];
                
                // 合并轨迹点，避免重复
                const existingPoints = existingTrack.points || [];
                const newPoints = trackData.points || [];
                
                // 创建时间戳映射，用于去重
                const existingTimestamps = new Set(existingPoints.map(p => p.timestamp_absolute));
                
                // 添加新的轨迹点（不重复的）
                const uniqueNewPoints = newPoints.filter(point => 
                    !existingTimestamps.has(point.timestamp_absolute)
                );
                
                if (uniqueNewPoints.length > 0) {
                    // 合并轨迹点并按时间排序
                    const allPoints = [...existingPoints, ...uniqueNewPoints].sort((a, b) => 
                        a.timestamp_absolute - b.timestamp_absolute
                    );
                    
                    // 更新轨迹数据
                    const updatedTrackData = {
                        ...trackData,
                        points: allPoints
                    };
                    
                    this.flightTracks[trackIndex] = updatedTrackData;
                    
                    // 移除轨迹线更新，性能优先
                    // this.updateTrackPolyline(trackId, updatedTrackData);
                    
                    // 移除飞机位置更新，只在渲染循环中更新
                    // this.updateAircraftPosition(trackId, updatedTrackData);
                    
                    // 更新轨迹属性面板
                     if (this.selectedTrackId === trackId) {
                         this.selectedTrackData = updatedTrackData;
                         if (allPoints.length > 0) {
                             // 更新最近10个轨迹点
                             this.recentTrackPoints = allPoints.slice(-10).reverse();
                             this.currentTrackPoint = allPoints[allPoints.length - 1];
                             // 更新倒数第二个轨迹点
                             if (allPoints.length >= 2) {
                                 this.previousTrackPoint = allPoints[allPoints.length - 2];
                             }
                             // 更新倒数第三个轨迹点
                             if (allPoints.length >= 3) {
                                 this.thirdLastTrackPoint = allPoints[allPoints.length - 3];
                             }
                             // 更新倒数第四个轨迹点
                             if (allPoints.length >= 4) {
                                 this.fourthLastTrackPoint = allPoints[allPoints.length - 4];
                             }
                         }
                     }
                     
                     // 更新第二个轨迹数据（如果存在）
                     if (this.flightTracks.length >= 2) {
                         this.secondTrackData = this.flightTracks[1];
                     }
                     
                     // 移除标签更新，性能优先
                     // this._taskNameCache = {};
                     // this.updateAllAircraftLabels();
                    
                    // 立即更新飞机位置到最新点
                    this.updateAircraftPosition(trackId, updatedTrackData);
                    
                    // console.log(`轨迹 ${trackId} 新增 ${uniqueNewPoints.length} 个轨迹点，总计 ${allPoints.length} 个点`);
                }
            }
        },
        
        // ================= 实时渲染相关 =================
        initRealTimeRendering() {
            // 启动实时渲染定时器（如果启用实时更新）
            if (this.enableRealTimeUpdate) {
                this.renderInterval = setInterval(() => {
                    this.renderNewPoints();
                }, this.renderDelay);
            }
        },
        
                 renderNewPoints() {
             const currentTime = Date.now();
             
             // 节流控制，避免过于频繁的更新
             if (currentTime - this.lastUpdateTime < this.updateThrottle) {
                 return;
             }
             
             // 批量更新所有轨迹和飞机位置，减少渲染次数
             this.flightTracks.forEach(track => {
                 if (track.points && track.points.length > 0) {
                     // 更新轨迹线（包括颜色）
                     this.updateTrackPolylinePositions(track.id, track);
                     
                     // 更新飞机位置
                     this.updateAircraftPosition(track.id, track);
                 }
             });
             
             this.lastRenderTime = currentTime;
             this.lastUpdateTime = currentTime;
         },
        
                 createTrackPolyline(trackId, trackData) {
             // 安全检查：确保参数有效
             if (!trackId || !trackData) {
                 console.warn('createTrackPolyline: 参数无效', { trackId, trackData });
                 return;
             }
             
             // 安全检查：确保trackPolylines存在
             if (!this.trackPolylines) {
                 this.trackPolylines = {};
             }
             
             // 创建轨迹线实体 - 使用静态位置数组，避免频繁的CallbackProperty调用
             const polylineEntity = this.viewer.entities.add({
                 polyline: {
                     positions: [], // 初始为空数组
                     width: 5, // 增加宽度，让轨迹线更明显
                     material: Cesium.Color.CYAN.withAlpha(0.8), // 默认使用青色
                     clampToGround: false,
                     show: this.showHistoricalTracks, // 根据设置控制可见性
                     zIndex: 100 // 设置图层顺序，确保轨迹线在航线上方
                 }
             });
             
             // 存储实体引用，用于后续更新
             this.trackPolylines[trackId] = polylineEntity;
             
             // 立即更新轨迹线
             this.updateTrackPolylinePositions(trackId, trackData);
             
             // 隐藏起点标签 - 不显示任何起点信息
             // if (trackData.points.length > 0) {
             //     const startPoint = trackData.points[0];
             //     
             //     // 验证起点坐标的有效性
             //     if (startPoint && 
             //         typeof startPoint.longitude === 'number' && !isNaN(startPoint.longitude) &&
             //         typeof startPoint.latitude === 'number' && !isNaN(startPoint.latitude) &&
             //         typeof startPoint.altitude === 'number' && !isNaN(startPoint.altitude) &&
             //         startPoint.longitude >= -180 && startPoint.longitude <= 180 &&
             //         startPoint.latitude >= -90 && startPoint.latitude <= 90) {
             //         
             //         const labelText = trackData.aircraft_type ? 
             //             `${trackData.aircraft_type}\n${trackData.mission_type || '轨迹'}` : 
             //             `轨迹${this.flightTracks.length}`;
             //         
             //         try {
             //             this.viewer.entities.add({
             //                 position: Cesium.Cartesian3.fromDegrees(startPoint.longitude, startPoint.latitude, startPoint.altitude),
             //                 label: {
             //                     text: labelText,
             //                     font: '12pt sans-serif',
             //                     style: Cesium.LabelStyle.FILL_AND_OUTLINE,
             //                     outlineWidth: 2,
             //                     verticalOrigin: Cesium.VerticalOrigin.TOP,
             //                     pixelOffset: new Cesium.Cartesian2(0, 10),
             //                     fillColor: trackData.color,
             //                     outlineColor: Cesium.Color.BLACK
             //                 }
             //             });
             //         } catch (e) {
             //             console.warn('创建起点标签失败:', startPoint, e);
             //         }
             //     }
             // }
         },
        
        updateTrackPolyline(trackId, trackData) {
            // 更新轨迹线位置
            this.updateTrackPolylinePositions(trackId, trackData);
        },
        
                 updateTrackPolylinePositions(trackId, trackData) {
             const polylineEntity = this.trackPolylines[trackId];
             if (!polylineEntity) return;
             
             const positions = [];
             const currentTime = Date.now();
             
             trackData.points.forEach(point => {
                 // 验证坐标数据的有效性
                 if (point && 
                     typeof point.longitude === 'number' && !isNaN(point.longitude) &&
                     typeof point.latitude === 'number' && !isNaN(point.latitude) &&
                     typeof point.altitude === 'number' && !isNaN(point.altitude) &&
                     point.longitude >= -180 && point.longitude <= 180 &&
                     point.latitude >= -90 && point.latitude <= 90) {
                     try {
                         positions.push(Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.altitude));
                     } catch (e) {
                         console.warn('无效的坐标点:', point, e);
                     }
                 }
             });
             
             // 批量更新位置，减少渲染次数
             if (positions.length >= 2) {
                 polylineEntity.polyline.positions = positions;
                 
                 // 更新轨迹线颜色：飞过的轨迹用青色，未来的轨迹用原色
                 this.updateTrackPolylineColor(trackId, trackData, currentTime);
             }
         },
         
         updateTrackPolylineColor(trackId, trackData, currentTime) {
             const polylineEntity = this.trackPolylines[trackId];
             if (!polylineEntity || !trackData.points || trackData.points.length === 0) return;
             
             // 对于实时轨迹，飞过的轨迹用青色显示
             polylineEntity.polyline.material = Cesium.Color.CYAN.withAlpha(0.8);
         },
         

         

         

         
         // 创建分段颜色的轨迹线（更精确的方法）
         // 移除分段轨迹线创建，性能优先
        
                          createAircraftEntity(trackId, trackData) {
             // 安全检查：确保参数有效
             if (!trackId || !trackData) {
                 console.warn('createAircraftEntity: 参数无效', { trackId, trackData });
                 return;
             }
             
             // 安全检查：确保aircraftEntities存在
             if (!this.aircraftEntities) {
                 this.aircraftEntities = {};
             }
             
             // 获取初始位置
             let initialPosition;
             if (trackData.points && trackData.points.length > 0) {
                 const firstPoint = trackData.points[0];
                 if (firstPoint && typeof firstPoint.longitude === 'number' && typeof firstPoint.latitude === 'number') {
                     initialPosition = Cesium.Cartesian3.fromDegrees(firstPoint.longitude, firstPoint.latitude, firstPoint.altitude || 1000);
                 } else {
                     initialPosition = Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 1000);
                 }
             } else {
                 initialPosition = Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 1000);
             }
             
             // 创建飞机实体（飞行器图标）- 使用动态位置CallbackProperty，支持实时移动
             const aircraftEntity = this.viewer.entities.add({
                 id: `aircraft-${trackId}`, // 设置唯一ID，用于点击识别
                 position: new Cesium.CallbackProperty(() => {
                     // 动态获取当前位置，支持实时移动
                     const track = this.flightTracks.find(t => t && t.id === trackId);
                     if (track && track.points && track.points.length > 0) {
                         // 计算当前时间对应的轨迹点
                         const currentTime = Date.now();
                         const currentPoint = this.getCurrentPointForAircraft(track, currentTime);
                         
                         if (currentPoint && 
                             typeof currentPoint.longitude === 'number' && !isNaN(currentPoint.longitude) &&
                             typeof currentPoint.latitude === 'number' && !isNaN(currentPoint.latitude) &&
                             typeof currentPoint.altitude === 'number' && !isNaN(currentPoint.altitude)) {
                             return Cesium.Cartesian3.fromDegrees(
                                 currentPoint.longitude, 
                                 currentPoint.latitude, 
                                 currentPoint.altitude
                             );
                         }
                         
                         // 如果没有找到当前点，返回最新点
                         const latestPoint = track.points[track.points.length - 1];
                         if (latestPoint && 
                             typeof latestPoint.longitude === 'number' && !isNaN(latestPoint.longitude) &&
                             typeof latestPoint.latitude === 'number' && !isNaN(latestPoint.latitude) &&
                             typeof latestPoint.altitude === 'number' && !isNaN(latestPoint.altitude)) {
                             return Cesium.Cartesian3.fromDegrees(
                                 latestPoint.longitude, 
                                 latestPoint.latitude, 
                                 latestPoint.altitude
                             );
                         }
                     }
                     // 如果无法获取位置，返回初始位置
                     return initialPosition;
                 }, false), // false表示不缓存，每次都重新计算
                 billboard: {
                     image: trackData.color ? this.createColoredDroneIcon(trackData.color) : this.createColoredDroneIcon(Cesium.Color.CYAN),
                     width: 48,
                     height: 48,
                     eyeOffset: new Cesium.Cartesian3(0, 0, -100),
                     alignedAxis: Cesium.Cartesian3.UNIT_Z, // 添加对齐轴
                     zIndex: 200 // 设置图层顺序，确保飞机在最上方
                 },
                 label: {
                     text: this.getTaskNameByTrackId(trackId) || trackData.aircraft_type || "未知任务",
                     font: '16pt Arial',
                     style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                     outlineWidth: 3,
                     verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                     pixelOffset: new Cesium.Cartesian2(0, -60),
                     show: true,
                     backgroundColor: Cesium.Color.BLACK.withAlpha(0.8),
                     fillColor: new Cesium.CallbackProperty(() => {
                         // 如果这个轨迹是当前选中的轨迹，使用红色，否则使用黄色
                         return trackId === this.selectedTrackId ? Cesium.Color.RED : Cesium.Color.YELLOW;
                     }, false),
                     outlineColor: Cesium.Color.BLACK,
                     outlineWidth: 2,
                     scale: 1.0,
                     heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
                     disableDepthTestDistance: Number.POSITIVE_INFINITY,
                     alwaysInFront: true
                 }
             });
             
             this.aircraftEntities[trackId] = aircraftEntity;
             
             // 飞机实体创建完成
             
             // 关联飞机实体到任务状态
             if (this.taskStatus[trackId]) {
                 this.taskStatus[trackId].aircraftEntity = aircraftEntity;
             }
             
             // 立即更新飞机位置
             this.updateAircraftPosition(trackId, trackData);
         },
        
                 updateAircraftPosition(trackId, trackData) {
             // 安全检查：确保aircraftEntities存在
             if (!this.aircraftEntities) {
                 this.aircraftEntities = {};
                 return;
             }
             
             const aircraftEntity = this.aircraftEntities[trackId];
             if (!aircraftEntity) return;
             
             // 安全检查：确保轨迹缓存对象存在
             if (!this._trackCache) {
                 this._trackCache = {};
             }
             
             // 直接查找轨迹，不使用缓存
             let track = this.flightTracks.find(t => t && t.id === trackId);
             
             // 轨迹查找完成
             
             if (!track || !track.points || track.points.length === 0) return;
             
             // 找到当前时间对应的点
             const currentTime = Date.now();
             const currentPoint = this.getCurrentPoint(track, currentTime);
             
             if (currentPoint && 
                 typeof currentPoint.longitude === 'number' && !isNaN(currentPoint.longitude) &&
                 typeof currentPoint.latitude === 'number' && !isNaN(currentPoint.latitude) &&
                 typeof currentPoint.altitude === 'number' && !isNaN(currentPoint.altitude) &&
                 currentPoint.longitude >= -180 && currentPoint.longitude <= 180 &&
                 currentPoint.latitude >= -90 && currentPoint.latitude <= 90) {
                 try {
                     // 直接更新飞机位置到最新点
                     aircraftEntity.position = Cesium.Cartesian3.fromDegrees(
                         currentPoint.longitude, 
                         currentPoint.latitude, 
                         currentPoint.altitude
                     );
                     
                     // 飞机位置更新完成
                     
                     // 检查任务完成状态
                     this.checkTaskCompletion(trackId, currentPoint);
                     
                     // 移除标签频繁更新，只在创建时设置一次
                     // 标签文本在创建时已经设置，不需要每次更新
                 } catch (e) {
                     console.warn('更新飞机位置失败:', currentPoint, e);
                 }
             }
         },
        
                 getCurrentPoint(track, currentTime) {
             if (!track.points || track.points.length === 0) return null;
             
             // 验证轨迹点数据的有效性
             const validPoints = track.points.filter(point => 
                 point && 
                 typeof point.longitude === 'number' && !isNaN(point.longitude) &&
                 typeof point.latitude === 'number' && !isNaN(point.latitude) &&
                 typeof point.altitude === 'number' && !isNaN(point.altitude) &&
                 point.longitude >= -180 && point.longitude <= 180 &&
                 point.latitude >= -90 && point.latitude <= 90
             );
             
             if (validPoints.length === 0) return null;
             
             // 对于实时轨迹，直接返回最新的点
             const latestPoint = validPoints[validPoints.length - 1];
             
             // 当前点获取完成
             
             return latestPoint;
         },
         
         // 移除复杂的朝向计算，性能优先
         
         // 移除方位角计算，性能优先
         
         // 移除方向计算，性能优先
         
         addPointsToTrack(trackId, newPoints) {
             // 这里可以添加新点到轨迹的逻辑
             // 由于使用了CallbackProperty，轨迹线会自动更新
         },
        
                 clearAllTracks() {
             if (confirm('确定要清除所有轨迹吗？')) {
                 // 停止播放
                 this.stopPlayback();
                 
                 // 清除所有轨迹实体
                 Object.values(this.trackPolylines).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 Object.values(this.aircraftEntities).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 
                 // 清空数据
                 this.trackPolylines = {};
                 this.aircraftEntities = {};
                 this.flightTracks = [];
                 this.currentTrackIndex = 0;
                 this.flightPath = [];
                 
                 // 重置时间轴
                 this.currentTime = 0;
                 this.totalDuration = 0;
                 this.currentTimePercent = 0;
                 
                 // 重置飞行方向
                 this.lastHeading = null;
                 this.headingText = '-';
                 
                 this.status = '已清除所有轨迹';
             }
         },
         
         // 清空所有轨迹（不需要确认）
         clearAllTracksWithoutConfirm() {
             // 停止播放
             this.stopPlayback();
             
             // 清除所有轨迹实体
             Object.values(this.trackPolylines).forEach(entity => {
                 if (entity) this.viewer.entities.remove(entity);
             });
             Object.values(this.aircraftEntities).forEach(entity => {
                 if (entity) this.viewer.entities.remove(entity);
             });
             
             // 清空数据
             this.trackPolylines = {};
             this.aircraftEntities = {};
             this.flightTracks = [];
             this.currentTrackIndex = 0;
             this.flightPath = [];
             
             // 重置时间轴
             this.currentTime = 0;
             this.totalDuration = 0;
             this.currentTimePercent = 0;
             
             // 重置飞行方向
             this.lastHeading = null;
             this.headingText = '-';
             
             this.status = '已清空所有实时轨迹';
             
             // 清空轨迹属性面板数据
             this.selectedTrackId = '';
             this.selectedTrackData = null;
             this.currentTrackPoint = null;
             this.secondTrackData = null;
             this.previousTrackPoint = null;
             this.thirdLastTrackPoint = null;
             this.fourthLastTrackPoint = null;
             this.recentTrackPoints = [];
             // 移除任务名称缓存清理，性能优先
         },
         
         // 设置飞行器点击事件处理器
         setupAircraftClickHandler() {
             if (!this.viewer) return;
             
             // 添加点击事件监听器
             this.aircraftClickHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
             
             this.aircraftClickHandler.setInputAction((click) => {
                 const pickedObject = this.viewer.scene.pick(click.position);
                 
                 if (pickedObject && pickedObject.id) {
                     const entity = pickedObject.id;
                     
                     // 检查是否是飞行器实体
                     if (entity.id && entity.id.startsWith('aircraft-')) {
                         const trackId = entity.id.replace('aircraft-', '');
                         console.log('点击了飞行器:', trackId);
                         
                         // 自动选中对应的轨迹下拉框
                         this.selectTrackByTid(trackId);
                         
                         // 显示功能按钮
                         this.showFunctionButtons = true;
                         
                         // 自动启动实时移动（调用测试移动的逻辑，但使用实时数据）
                         this.startRealTimeMovement(trackId);
                         
                         // 根据tid从任务列表中获取任务信息
                         this.updateSelectedTaskInfo(trackId);
                         
                         // 更新状态
                         this.status = `已选中轨迹${trackId}，功能按钮已激活，实时移动已启动`;
                     }
                 }
             }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
             
             console.log('飞行器点击事件处理器已设置');
         },
         
         // 根据trackId更新选中的任务信息
         updateSelectedTaskInfo(trackId) {
             if (!trackId) return;
             
             try {
                 // 获取轨迹数据
                 const track = this.flightTracks.find(t => t && (t.id === trackId || t.tid === trackId));
                 
                 if (track && track.tid) {
                     // 根据tid从任务列表中查找任务信息
                     const taskInfo = this.taskList.find(task => task.uuid === track.tid);
                     
                     if (taskInfo) {
                         console.log(`找到任务信息:`, taskInfo);
                         this.selectedTaskInfo = taskInfo;
                     } else {
                         console.warn(`未找到tid为${track.tid}的任务信息`);
                         this.selectedTaskInfo = null;
                     }
                 } else {
                     console.warn(`轨迹${trackId}没有关联的任务ID`);
                     this.selectedTaskInfo = null;
                 }
             } catch (error) {
                 console.error('更新任务信息失败:', error);
                 this.selectedTaskInfo = null;
             }
         },
         
         // 根据tid自动选中对应的轨迹下拉框
         selectTrackByTid(trackId) {
             if (!trackId) return;
             
             try {
                 console.log(`尝试根据tid ${trackId} 选中轨迹，当前轨迹列表:`, this.flightTracks);
                 
                 // 首先尝试通过tid查找轨迹（task.tid = dropdown.tid）
                 let track = this.flightTracks.find(t => t && t.tid === trackId);
                 
                 // 如果没找到，再尝试通过id查找
                 if (!track) {
                     track = this.flightTracks.find(t => t && t.id === trackId);
                 }
                 
                 if (track) {
                     // 直接设置选中的轨迹ID
                     this.selectedTrackId = track.id;
                     
                     // 更新选中的轨迹数据
                     this.selectedTrackData = track;
                     
                     console.log(`已自动选中轨迹: tid=${trackId} -> 轨迹ID=${track.id}, 轨迹数据:`, track);
                     
                     // 触发轨迹选择变化事件
                     this.onTrackSelectionChange();
                     
                     return true;
                 } else {
                     console.warn(`未找到tid为${trackId}的轨迹数据，当前轨迹列表:`, this.flightTracks);
                     return false;
                 }
             } catch (error) {
                 console.error('自动选中轨迹失败:', error);
                 return false;
             }
         },
         
         // 返回默认模式
         returnToDefaultMode() {
             // 隐藏功能按钮
             this.showFunctionButtons = false;
             
             // 清除选中的轨迹
             this.selectedTrackId = '';
             this.selectedTrackData = null;
             
             // 清除选中的任务信息
             this.selectedTaskInfo = null;
             
             // 停止所有跟踪
             this.stopTrackingAircraft();
             
             // 停止持续跟随
             if (this.continuousFollowTimer) {
                 clearInterval(this.continuousFollowTimer);
                 this.continuousFollowTimer = null;
             }
             
             // 停止实时移动
             this.stopRealTimeMovement();
             
             // 清除跟踪状态
             this.currentTrackedAircraftId = null;
             this.currentViewMode = null;
             
             // 恢复默认相机视角
             this.resetCameraToDefault();
             
             console.log('已返回默认模式');
             this.status = '已返回默认地图模式';
         },
         
         // 重置相机到默认视角
         resetCameraToDefault() {
             if (!this.viewer) return;
             
             try {
                 // 设置默认相机位置（北京上空）
                 this.viewer.camera.setView({
                     destination: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 1000000),
                     orientation: {
                         heading: 0.0,
                         pitch: -Cesium.Math.PI_OVER_TWO + 0.1,
                         roll: 0.0
                     }
                 });
                 
                 console.log('相机已重置到默认视角');
             } catch (error) {
                 console.error('重置相机失败:', error);
             }
         },
         
         // 跟随视角跟踪飞行器
         trackAircraft(trackId) {
             if (!this.viewer || !trackId) return;
             
             try {
                 const aircraftEntity = this.aircraftEntities[trackId];
                 if (aircraftEntity) {
                     // 使用Cesium自带的跟踪功能
                     this.viewer.trackedEntity = aircraftEntity;
                     
                     // 设置合适的相机距离和角度
                     const position = aircraftEntity.position.getValue(Cesium.JulianDate.now());
                     if (position) {
                         const cartographic = Cesium.Cartographic.fromCartesian(position);
                         const offsetPosition = Cesium.Cartesian3.fromDegrees(
                             Cesium.Math.toDegrees(cartographic.longitude),
                             Cesium.Math.toDegrees(cartographic.latitude),
                             cartographic.height + 3000 // 高度偏移3000米
                         );
                         
                         this.viewer.camera.setView({
                             destination: offsetPosition,
                             orientation: {
                                 heading: 0.0,
                                 pitch: -Cesium.Math.PI_OVER_TWO + 0.2, // 向下看20度
                                 roll: 0.0
                             }
                         });
                     }
                     
                     // 设置当前跟踪的飞行器ID
                     this.currentTrackedAircraftId = trackId;
                     this.currentViewMode = 'track';
                     
                     console.log(`已开始跟随视角跟踪轨迹${trackId}的飞行器`);
                     this.status = `正在跟随视角跟踪轨迹${trackId}的飞行器`;
                 }
             } catch (error) {
                 console.error('跟踪飞行器失败:', error);
                 this.status = '跟踪飞行器失败';
             }
         },
         
         // 切换到第一视角
         switchToFirstPersonView(trackId) {
             if (!this.viewer || !trackId) return;
             
             try {
                 const aircraftEntity = this.aircraftEntities[trackId];
                 if (aircraftEntity) {
                     // 停止跟踪
                     this.viewer.trackedEntity = undefined;
                     
                     // 设置第一视角
                     const position = aircraftEntity.position.getValue(Cesium.JulianDate.now());
                     if (position) {
                         this.viewer.camera.setView({
                             destination: position,
                             orientation: {
                                 heading: 0.0,
                                 pitch: 0.0,
                                 roll: 0.0
                             }
                         });
                         
                         // 设置当前跟踪的飞行器ID和视图模式
                         this.currentTrackedAircraftId = trackId;
                         this.currentViewMode = 'first_person';
                         
                         console.log(`已切换到第一视角`);
                         this.status = `已切换到第一视角`;
                     }
                 }
             } catch (error) {
                 console.error('切换到第一视角失败:', error);
                 this.status = '切换到第一视角失败';
             }
         },
         
         // 停止跟踪飞行器
         stopTrackingAircraft() {
             if (this.viewer) {
                 this.viewer.trackedEntity = undefined;
                 console.log('已停止跟踪飞行器');
             }
         },
         
         // 调试飞行器点击功能
         debugAircraftClick() {
             console.log('=== 调试飞行器点击功能 ===');
             console.log('viewer状态:', !!this.viewer);
             console.log('aircraftClickHandler状态:', !!this.aircraftClickHandler);
             console.log('aircraftEntities:', this.aircraftEntities);
             
             if (this.aircraftEntities && Object.keys(this.aircraftEntities).length > 0) {
                 console.log('飞行器实体详情:');
                 Object.keys(this.aircraftEntities).forEach(trackId => {
                     const entity = this.aircraftEntities[trackId];
                     console.log(`轨迹${trackId}:`, {
                         'entity.id': entity.id,
                         'entity.position': entity.position,
                         'entity.billboard': entity.billboard
                     });
                 });
             } else {
                 console.log('没有找到飞行器实体');
             }
             
             this.status = '飞行器点击功能调试信息已输出到控制台';
         },
         
         // 调试轨迹数据
         debugTrackData() {
             console.log('=== 调试轨迹数据 ===');
             console.log('flightTracks:', this.flightTracks);
             console.log('selectedTrackId:', this.selectedTrackId);
             console.log('selectedTrackData:', this.selectedTrackData);
             console.log('showFunctionButtons:', this.showFunctionButtons);
             
             this.status = '轨迹数据调试信息已输出到控制台';
         },
         
         // 调试WebSocket连接
         debugWebSocket() {
             console.log('=== 调试WebSocket连接 ===');
             console.log('websocket对象:', this.websocket);
             console.log('websocketUrl:', this.websocketUrl);
             
             if (this.websocket) {
                 console.log('WebSocket状态:', this.websocket.readyState);
                 console.log('WebSocket URL:', this.websocket.url);
                 console.log('WebSocket协议:', this.websocket.protocol);
                 console.log('WebSocket扩展:', this.websocket.extensions);
                 
                 switch (this.websocket.readyState) {
                     case WebSocket.CONNECTING:
                         console.log('WebSocket状态: 连接中 (0)');
                         break;
                     case WebSocket.OPEN:
                         console.log('WebSocket状态: 已连接 (1)');
                         break;
                     case WebSocket.CLOSING:
                         console.log('WebSocket状态: 关闭中 (2)');
                         break;
                     case WebSocket.CLOSED:
                         console.log('WebSocket状态: 已关闭 (3)');
                         break;
                     default:
                         console.log('WebSocket状态: 未知');
                 }
             } else {
                 console.log('WebSocket对象不存在');
             }
             
             this.status = 'WebSocket连接调试信息已输出到控制台';
         },
         
         // 强制显示功能按钮
         forceShowButtons() {
             if (this.selectedTrackId) {
                 this.showFunctionButtons = true;
                 this.status = '已强制显示功能按钮';
                 console.log('强制显示功能按钮');
             } else {
                 this.status = '请先选择一个轨迹';
             }
         },
         
         // 获取飞行器当前应该处于的轨迹点位置（支持实时移动）
         getCurrentPointForAircraft(track, currentTime) {
             if (!track || !track.points || track.points.length === 0) return null;
             
             // 验证轨迹点数据的有效性
             const validPoints = track.points.filter(point => 
                 point && 
                 typeof point.longitude === 'number' && !isNaN(point.longitude) &&
                 typeof point.latitude === 'number' && !isNaN(point.latitude) &&
                 typeof point.altitude === 'number' && !isNaN(point.altitude)
             );
             
             if (validPoints.length === 0) return null;
             
             // 如果轨迹只有一个点，直接返回
             if (validPoints.length === 1) {
                 return validPoints[0];
             }
             
             // 计算轨迹的总时长
             const firstPoint = validPoints[0];
             const lastPoint = validPoints[validPoints.length - 1];
             
             if (!firstPoint.timestamp_absolute || !lastPoint.timestamp_absolute) {
                 // 如果没有时间戳，使用模拟时间
                 return this.getSimulatedCurrentPoint(validPoints, currentTime);
             }
             
             const totalDuration = lastPoint.timestamp_absolute - firstPoint.timestamp_absolute;
             
             if (totalDuration <= 0) {
                 // 如果总时长为0或负数，使用模拟时间
                 return this.getSimulatedCurrentPoint(validPoints, currentTime);
             }
             
             // 计算当前时间在轨迹中的进度
             const elapsedTime = currentTime - firstPoint.timestamp_absolute * 1000; // 转换为毫秒
             const progress = Math.max(0, Math.min(1, elapsedTime / (totalDuration * 1000)));
             
             // 根据进度计算当前应该处于的轨迹点
             const pointIndex = Math.floor(progress * (validPoints.length - 1));
             const nextPointIndex = Math.min(pointIndex + 1, validPoints.length - 1);
             
             if (pointIndex === nextPointIndex) {
                 return validPoints[pointIndex];
             }
             
             // 在两个点之间进行插值
             const point1 = validPoints[pointIndex];
             const point2 = validPoints[nextPointIndex];
             const segmentProgress = (progress * (validPoints.length - 1)) - pointIndex;
             
             return {
                 longitude: point1.longitude + (point2.longitude - point1.longitude) * segmentProgress,
                 latitude: point1.latitude + (point2.latitude - point1.latitude) * segmentProgress,
                 altitude: point1.altitude + (point2.altitude - point1.altitude) * segmentProgress
             };
         },
         
         // 获取模拟的当前轨迹点（用于没有时间戳的情况）
         getSimulatedCurrentPoint(validPoints, currentTime) {
             if (validPoints.length === 0) return null;
             
             // 使用当前时间的秒数来模拟轨迹进度
             const seconds = Math.floor(currentTime / 1000);
             const cycleTime = 60; // 60秒一个循环
             const cycleProgress = (seconds % cycleTime) / cycleTime;
             
             // 根据循环进度计算当前点
             const pointIndex = Math.floor(cycleProgress * validPoints.length);
             return validPoints[pointIndex];
         },
         
         // 启动持续跟随模式
         startContinuousFollow(trackId) {
             if (!this.viewer || !trackId) return;
             
             try {
                 // 停止之前的跟踪
                 this.viewer.trackedEntity = undefined;
                 
                 // 启动持续跟随定时器
                 if (this.continuousFollowTimer) {
                     clearInterval(this.continuousFollowTimer);
                 }
                 
                 this.continuousFollowTimer = setInterval(() => {
                     const aircraftEntity = this.aircraftEntities[trackId];
                     if (aircraftEntity && aircraftEntity.position) {
                         const position = aircraftEntity.position.getValue(Cesium.JulianDate.now());
                         if (position) {
                             const cartographic = Cesium.Cartographic.fromCartesian(position);
                             const offsetPosition = Cesium.Cartesian3.fromDegrees(
                                 Cesium.Math.toDegrees(cartographic.longitude),
                                 Cesium.Math.toDegrees(cartographic.latitude),
                                 cartographic.height + 3000
                             );
                             
                             // 平滑移动相机
                             this.viewer.camera.setView({
                                 destination: offsetPosition,
                                 orientation: {
                                     heading: 0.0,
                                     pitch: -Cesium.Math.PI_OVER_TWO + 0.2,
                                     roll: 0.0
                                 },
                                 duration: 0.1 // 快速跟随
                             });
                         }
                     }
                 }, 100); // 每100ms更新一次
                 
                 // 设置当前跟踪的飞行器ID和视图模式
                 this.currentTrackedAircraftId = trackId;
                 this.currentViewMode = 'continuous';
                 
                 console.log(`已启动持续跟随模式，跟踪轨迹${trackId}`);
                 this.status = `正在持续跟随轨迹${trackId}的飞行器`;
                 
             } catch (error) {
                 console.error('启动持续跟随失败:', error);
                 this.status = '启动持续跟随失败';
             }
         },
         
         // 相机跟随飞行器到新位置
         followAircraftToNewPosition(newPoint) {
             if (!this.viewer || !newPoint) return;
             
             try {
                 // 计算相机应该跟随的位置（稍微偏移，避免完全重叠）
                 const cameraPosition = Cesium.Cartesian3.fromDegrees(
                     newPoint.longitude,
                     newPoint.latitude,
                     newPoint.altitude + 5000 // 高度偏移5000米
                 );
                 
                 // 平滑移动相机到新位置
                 this.viewer.camera.flyTo({
                     destination: cameraPosition,
                     orientation: {
                         heading: 0.0,
                         pitch: -Cesium.Math.PI_OVER_TWO + 0.2, // 向下看20度
                         roll: 0.0
                     },
                     duration: 1.0, // 1秒动画
                     complete: () => {
                         // console.log('相机已跟随到新位置');
                         this.status = '相机已跟随飞行器到新位置';
                     }
                 });
                 
             } catch (error) {
                 // console.error('相机跟随失败:', error);
                 this.status = '相机跟随失败';
             }
         },
         
         // 启动实时移动（使用动态实时数据）
         startRealTimeMovement(trackId) {
             if (!trackId) return;
             
             try {
                 const track = this.flightTracks.find(t => t && t.id === trackId);
                 if (!track || !track.points || track.points.length === 0) {
                     // console.warn('没有找到轨迹数据，无法启动实时移动');
                     return;
                 }
                 
                 // console.log(`启动轨迹${trackId}的实时移动`);
                 
                 // 启动实时移动定时器
                 if (this.realTimeMovementTimer) {
                     clearInterval(this.realTimeMovementTimer);
                 }
                 
                 this.realTimeMovementTimer = setInterval(() => {
                     // 获取当前时间对应的轨迹点
                     const currentTime = Date.now();
                     const currentPoint = this.getCurrentPointForAircraft(track, currentTime);
                     
                     if (currentPoint) {
                         // 更新轨迹数据，添加新的实时点
                         const newPoint = {
                             longitude: currentPoint.longitude,
                             latitude: currentPoint.latitude,
                             altitude: currentPoint.altitude,
                             timestamp_absolute: currentTime / 1000,
                             speed: currentPoint.speed || 0,
                             battery: currentPoint.battery || 100
                         };
                         
                         // 添加到轨迹中（如果点不重复）
                         const lastPoint = track.points[track.points.length - 1];
                         if (!lastPoint || 
                             Math.abs(lastPoint.longitude - newPoint.longitude) > 0.000001 ||
                             Math.abs(lastPoint.latitude - newPoint.latitude) > 0.000001) {
                             track.points.push(newPoint);
                             
                             // 限制轨迹点数量，避免内存占用过大
                             if (track.points.length > 1000) {
                                 track.points = track.points.slice(-500);
                             }
                             
                             // 强制刷新Cesium渲染
                             this.viewer.scene.requestRender();
                             
                             console.log(`轨迹${trackId}实时更新:`, newPoint);
                         }
                     }
                     
                 }, 1000); // 每秒更新一次
                 
                 this.status = `轨迹${trackId}实时移动已启动，每秒更新位置`;
                 
             } catch (error) {
                 console.error('启动实时移动失败:', error);
                 this.status = '启动实时移动失败';
             }
         },
         
         // 停止实时移动
         stopRealTimeMovement() {
             if (this.realTimeMovementTimer) {
                 clearInterval(this.realTimeMovementTimer);
                 this.realTimeMovementTimer = null;
                 console.log('实时移动已停止');
                 this.status = '实时移动已停止';
             }
         },
         
         // 测试飞行器移动
         testAircraftMovement() {
             if (!this.selectedTrackId) {
                 this.status = '请先选择一个轨迹';
                 return;
             }
             
             const track = this.flightTracks.find(t => t && t.id === this.selectedTrackId);
             if (!track || !track.points || track.points.length === 0) {
                 this.status = '选中的轨迹没有数据';
                 return;
             }
             
             // 添加模拟的移动轨迹点
             const lastPoint = track.points[track.points.length - 1];
             const newPoint = {
                 longitude: lastPoint.longitude + (Math.random() - 0.5) * 0.01,
                 latitude: lastPoint.latitude + (Math.random() - 0.5) * 0.01,
                 altitude: lastPoint.altitude + (Math.random() - 0.5) * 100,
                 timestamp_absolute: Date.now() / 1000
             };
             
             track.points.push(newPoint);
             
             // 更新飞行器位置到新点
             const aircraftEntity = this.aircraftEntities[this.selectedTrackId];
             if (aircraftEntity) {
                 aircraftEntity.position = Cesium.Cartesian3.fromDegrees(
                     newPoint.longitude,
                     newPoint.latitude,
                     newPoint.altitude
                 );
                 
                 // 相机跟随到新位置
                 this.followAircraftToNewPosition(newPoint);
             }
             
             this.viewer.scene.requestRender();
             
             this.status = `已添加测试轨迹点，飞行器已移动到新位置`;
             console.log('测试轨迹点已添加:', newPoint);
         },
         
         // 轨迹选择变化处理
         onTrackSelectionChange() {
             if (this.isUpdatingSelection) return; // 防止循环调用
             
             if (this.selectedTrackId) {
                 // 查找选中的轨迹数据
                 this.selectedTrackData = this.flightTracks.find(track => track.id === this.selectedTrackId);
                 
                 // 同步更新左边面板的选择
                 const trackIndex = this.flightTracks.findIndex(track => track.id === this.selectedTrackId);
                 if (trackIndex !== -1) {
                     this.isUpdatingSelection = true;
                     this.currentTrackIndex = trackIndex;
                     this.currentTrack = this.selectedTrackData;
                     this.flightPath = this.selectedTrackData.points;
                     this.initializeTimeline();
                     this.isUpdatingSelection = false;
                 }
                 
                 // 获取第二个轨迹数据（如果存在）
                 if (this.flightTracks.length >= 2) {
                     this.secondTrackData = this.flightTracks[1]; // 第二个轨迹
                 } else {
                     this.secondTrackData = null;
                 }
                 
                 // 清除任务名称缓存，重新计算
                 // 移除任务名称缓存清理，性能优先
                 // 移除标签更新，性能优先
                 
                 if (this.selectedTrackData && this.selectedTrackData.points && this.selectedTrackData.points.length > 0) {
                     const points = this.selectedTrackData.points;
                     // 获取最近10个轨迹点（倒置顺序，最新在最前面）
                     this.recentTrackPoints = points.slice(-10).reverse();
                     // 保留原有的单个轨迹点数据（用于兼容性）
                     this.currentTrackPoint = points[points.length - 1];
                     if (points.length >= 2) {
                         this.previousTrackPoint = points[points.length - 2];
                     } else {
                         this.previousTrackPoint = null;
                     }
                     if (points.length >= 3) {
                         this.thirdLastTrackPoint = points[points.length - 3];
                     } else {
                         this.thirdLastTrackPoint = null;
                     }
                     if (points.length >= 4) {
                         this.fourthLastTrackPoint = points[points.length - 4];
                     } else {
                         this.fourthLastTrackPoint = null;
                     }
                 } else {
                     this.recentTrackPoints = [];
                     this.currentTrackPoint = null;
                     this.previousTrackPoint = null;
                     this.thirdLastTrackPoint = null;
                     this.fourthLastTrackPoint = null;
                 }
             } else {
                 this.selectedTrackData = null;
                 this.currentTrackPoint = null;
                 this.secondTrackData = null;
                 this.previousTrackPoint = null;
             }
         },
         
         // 更新当前轨迹点数据
         updateCurrentTrackPoint(trackId, pointData) {
             if (this.selectedTrackId === trackId && this.selectedTrackData) {
                 this.currentTrackPoint = pointData;
             }
         },
         
         // 获取当前日期（年月日）
         getCurrentDate() {
             if (this.recentTrackPoints && this.recentTrackPoints.length > 0) {
                 // 从第一条轨迹点获取日期
                 const firstPoint = this.recentTrackPoints[0];
                 if (firstPoint && firstPoint.timestamp_absolute) {
                     const date = new Date(firstPoint.timestamp_absolute * 1000);
                     const year = date.getFullYear();
                     const month = String(date.getMonth() + 1).padStart(2, '0');
                     const day = String(date.getDate()).padStart(2, '0');
                     return `${year}-${month}-${day}`;
                 }
             }
             // 如果没有轨迹点数据，返回当前系统日期
             const now = new Date();
             const year = now.getFullYear();
             const month = String(now.getMonth() + 1).padStart(2, '0');
             const day = String(now.getDate()).padStart(2, '0');
             return `${year}-${month}-${day}`;
         },
         
         // 格式化时间（只显示小时分钟秒）
         formatTimeOnly(timestamp) {
             const date = new Date(timestamp * 1000);
             const hours = String(date.getHours()).padStart(2, '0');
             const minutes = String(date.getMinutes()).padStart(2, '0');
             const seconds = String(date.getSeconds()).padStart(2, '0');
             return `${hours}:${minutes}:${seconds}`;
         },
         
         // 格式化任务时间
         formatTaskTime(timeString) {
             if (!timeString) return 'N/A';
             try {
                 const date = new Date(timeString);
                 if (isNaN(date.getTime())) return 'N/A';
                 const hours = String(date.getHours()).padStart(2, '0');
                 const minutes = String(date.getMinutes()).padStart(2, '0');
                 return `${hours}:${minutes}`;
             } catch (e) {
                 return 'N/A';
             }
         },
         
         // 获取轨迹点在原始数组中的下标
         getPointIndex(point) {
             if (!this.selectedTrackData || !this.selectedTrackData.points) {
                 return 'N/A';
             }
             const index = this.selectedTrackData.points.findIndex(p => 
                 p.timestamp_absolute === point.timestamp_absolute &&
                 p.longitude === point.longitude &&
                 p.latitude === point.latitude
             );
             return index !== -1 ? index + 1 : 'N/A';
         },
         
         // 清空所有轨迹（不需要确认）
         clearAllTracksWithoutConfirm() {
             // 停止播放
             if (this.playbackInterval) {
                 clearInterval(this.playbackInterval);
                 this.playbackInterval = null;
             }
             
             // 清除所有飞行器实体
             if (this.aircraftEntities) {
                 Object.values(this.aircraftEntities).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 
                 // 清空飞行器实体引用
                 this.aircraftEntities = {};
             }
             
             // 清除所有轨迹线实体
             if (this.trackPolylines) {
                 Object.values(this.trackPolylines).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 
                 // 清空轨迹线引用
                 this.trackPolylines = {};
             }
             
             // 清空轨迹数据
             this.flightTracks = [];
             
             // 清空选中的轨迹
             this.selectedTrackId = '';
             this.selectedTrackData = null;
             
             this.status = '已清空所有轨迹';
         },
         
         // 环境切换处理
         onEnvChange() {
             // 清空所有数据
             this.clearAllTracksWithoutConfirm();
             this.clearAllRoutesWithoutConfirm();
             this.clearAllLandingFieldsWithoutConfirm();
             
             // 根据环境更新WebSocket地址和接口地址
             this.updateWebSocketUrl();
             
             // 根据环境设置vid和需求id
             if (this.currentEnv === 'dev') {
                 this.vid = 684;
                 this.schemaRequirementId = 815;
             } else if (this.currentEnv === 'test') {
                 this.vid = 660;
                 this.schemaRequirementId = 798;
             }
             
             // 显示环境信息
             const envNames = {
                 dev: '开发环境',
                 test: '测试环境',
                 prod: '生产环境'
             };
             
             this.status = `环境已切换到: ${envNames[this.currentEnv]} (${this.currentEnv})，所有数据已清空，vid=${this.vid}，需求id=${this.schemaRequirementId}`;
             
             // 如果当前已连接，断开WebSocket连接
             if (this.isConnected) {
                 this.disconnectWebSocket();
                 this.status = `环境已切换到: ${envNames[this.currentEnv]}，WebSocket已断开，请重新连接`;
             }
         },
         
         // 隐藏Cesium ion警告消息
         hideIonWarning() {
             // 方法1：通过CSS隐藏ion警告
             const style = document.createElement('style');
             style.textContent = `
                 .cesium-viewer-bottom {
                     display: none !important;
                 }
                 .cesium-viewer-cesiumWidgetContainer .cesium-widget-credits {
                     display: none !important;
                 }
             `;
             document.head.appendChild(style);
             
             // 方法2：直接移除ion警告元素
             setTimeout(() => {
                 const ionElements = document.querySelectorAll('.cesium-viewer-bottom, .cesium-widget-credits');
                 ionElements.forEach(el => {
                     if (el.textContent.includes('CESIUM ion') || el.textContent.includes('access token')) {
                         el.style.display = 'none';
                     }
                 });
             }, 1000);
         },
         
         // 根据环境更新WebSocket地址和接口地址
         updateWebSocketUrl() {
             const envConfigs = {
                 dev: {
                     ws: 'ws://127.0.0.1:6088/uam/v2/ws/uam/channel/245',
                     api: 'http://127.0.0.1:8084'
                 },
                 test: {
                     ws: 'ws://211.159.175.30:8011/uam/v2/ws/uam/channel/245',
                     api: 'http://211.159.175.30:8011'
                 },
                 prod: {
                     ws: 'ws://uam-cloud:8011/uam/v2/ws/uam/channel/245',
                     api: 'http://uam-cloud:8011'
                 }
             };
             
             const config = envConfigs[this.currentEnv] || envConfigs.test;
             this.websocketUrl = config.ws;
             this.apiBaseUrl = config.api;
         },
         
         // 获取轨迹总点数
         getTotalTrackPoints() {
             if (!this.selectedTrackData || !this.selectedTrackData.points) {
                 return 0;
             }
             return this.selectedTrackData.points.length;
         },
         
         // 分页相关方法
         goToPage(page) {
             if (page >= 1 && page <= this.totalPages) {
                 this.currentPage = page;
             }
         },
         
         // 任务列表分页相关方法
         goToFirstTaskPage() {
             this.currentTaskPage = 1;
         },
         
         goToPrevTaskPage() {
             if (this.currentTaskPage > 1) {
                 this.currentTaskPage--;
             }
         },
         
         goToNextTaskPage() {
             if (this.currentTaskPage < this.totalTaskPages) {
                 this.currentTaskPage++;
             }
         },
         
         goToLastTaskPage() {
             this.currentTaskPage = this.totalTaskPages;
         },
         
         onTaskPageSizeChange() {
             // 当页面大小改变时，重置到第一页
             this.currentTaskPage = 1;
         },
         
         onPageSizeChange() {
             // 当页面大小改变时，重置到第一页
             this.currentPage = 1;
         },
         
         // 跳转到指定任务所在的页面
         goToTaskPage(taskUuid) {
             const sortedTasks = this.sortedTaskList;
             const taskIndex = sortedTasks.findIndex(task => task.uuid === taskUuid);
             if (taskIndex !== -1) {
                 const page = Math.floor(taskIndex / this.pageSize) + 1;
                 this.goToPage(page);
             }
         },
         
         // 判断任务是否被选中（优化版本）
         isTaskSelected(taskUuid) {
             // 使用缓存避免重复计算
             if (!this._selectedTaskCache) {
                 this._selectedTaskCache = new Map();
             }
             
             const cacheKey = `${this.selectedTrackId}_${taskUuid}`;
             if (this._selectedTaskCache.has(cacheKey)) {
                 return this._selectedTaskCache.get(cacheKey);
             }
             
             if (!this.selectedTrackId) {
                 this._selectedTaskCache.set(cacheKey, false);
                 return false;
             }
             
             const selectedTrack = this.flightTracks.find(t => t.id === this.selectedTrackId);
             const result = selectedTrack && selectedTrack.tid === taskUuid;
             
             this._selectedTaskCache.set(cacheKey, result);
             return result;
         },
         
         // 清除选中任务缓存
         clearSelectedTaskCache() {
             this._selectedTaskCache = null;
         },
         
         // 清除所有性能缓存
         clearPerformanceCache() {
             this._selectedTaskCache = null;
             this._polylinePositionsCache = null;
             this._aircraftUpdateCache = null;
             // 移除任务名称缓存清理，性能优先
             this._trackCache = {};
             this._aircraftPositionCache = {};
         },
         
         // 性能监控
         logPerformanceStats() {
             const stats = {
                 轨迹数量: this.flightTracks.length,
                 轨迹点总数: this.flightTracks.reduce((sum, track) => sum + (track.points ? track.points.length : 0), 0),
                 飞机实体数量: Object.keys(this.aircraftEntities).length,
                 轨迹线实体数量: Object.keys(this.trackPolylines).length,
                 航线实体数量: this.routeEntities ? Object.keys(this.routeEntities).length : 0,
                 起降场数量: this.landingFieldEntities ? Object.keys(this.landingFieldEntities).length : 0,
                 白膜3DTiles: this.baimoTileset ? '已加载' : '未加载',
                 缓存命中率: {
                     轨迹缓存: Object.keys(this._trackCache).length,
                     位置缓存: Object.keys(this._aircraftPositionCache).length
                 },
                 渲染间隔: this.renderDelay,
                 节流间隔: this.updateThrottle,
                 任务完成检查: {
                     总检查次数: this.taskCompletionStats.totalChecks,
                     总耗时: this.taskCompletionStats.totalTime.toFixed(2) + 'ms',
                     平均耗时: this.taskCompletionStats.avgTime.toFixed(3) + 'ms'
                 }
             };
             
             console.log('性能统计:', stats);
             this.status = `性能统计: ${stats.轨迹数量}轨迹, ${stats.轨迹点总数}点, ${stats.飞机实体数量}飞机, ${stats.起降场数量}起降场, 白膜${stats.白膜3DTiles}, 渲染间隔${stats.渲染间隔}ms, 任务检查平均耗时${stats.任务完成检查.平均耗时}`;
         },
         
         // 重置任务完成检查性能统计
         resetTaskCompletionStats() {
             this.taskCompletionStats = { totalChecks: 0, totalTime: 0, avgTime: 0 };
             console.log('✅ 任务完成检查性能统计已重置');
             this.status = '任务完成检查性能统计已重置';
         },
         
         // 移除任务名称缓存，性能优先
         
         // 轨迹查找缓存
         _trackCache: {},
         
         // 根据轨迹ID获取任务名称
         getTaskNameByTrackId(trackId) {
             const track = this.flightTracks.find(t => t.id === trackId);
             if (!track) {
                 return '未知任务';
             }
             
             if (!track.tid) {
                 return '未知任务';
             }
             
             // 在任务列表中查找对应的任务（使用tid匹配uuid）
             const task = this.taskList.find(t => t.uuid === track.tid);
             if (task) {
                 return task.name;
             }
             
             // 如果任务列表为空，重新加载任务列表
             if (this.taskList.length === 0) {
                 if (this.isConnected && this.websocket && !this.isRequestingTasks) {
                     this.isRequestingTasks = true;
                     this.sendTaskMessage();
                     
                     // 延迟一段时间后再次尝试查找
                     setTimeout(() => {
                         const task = this.taskList.find(t => t.uuid === track.tid);
                         if (task) {
                             // 更新飞行器标签
                             const aircraftEntity = this.aircraftEntities[trackId];
                             if (aircraftEntity && aircraftEntity.label) {
                                 aircraftEntity.label.text = task.name;
                             }
                         }
                         this.isRequestingTasks = false;
                     }, 2000);
                 }
                 return '未知任务';
             }
             
             return '未知任务';
         },
         
         // 移除标签更新方法，性能优先
         
         // 清空方案ID
         clearPlanId() {
             this.planId = '';
             this.batchPlanId = 1;
             this.status = '已清空方案ID';
         },
         
         // 自动获取航线
         autoGetRoutes() {
             if (this.isConnected && this.websocket && this.planId) {
                 try {
                     const routeMessage = {
                         wsClientType: this.wsClientType || 1,
                         planId: parseInt(this.planId) || 1,
                         schemaRequirementId: parseInt(this.schemaRequirementId) || 798
                     };
                     this.websocket.send(JSON.stringify(routeMessage));
                     this.status = '已自动重新获取航线...';
                 } catch (error) {
                     console.error('自动获取航线失败:', error);
                     this.status = '自动获取航线失败';
                 }
             }
         },
         
         // 清空所有航线（不需要确认）
         clearAllRoutesWithoutConfirm() {
             // 清除所有航线实体
             if (this.routeEntities) {
                 Object.values(this.routeEntities).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 
                 // 清空航线实体引用
                 this.routeEntities = {};
             }
             
             this.status = '已清空所有航线';
         },
         
         // 清空所有起降场（不需要确认）
         clearAllLandingFieldsWithoutConfirm() {
             // 清除起降场实体
             if (this.landingFieldEntities) {
                 Object.values(this.landingFieldEntities).forEach(item => {
                     if (item.entity) this.viewer.entities.remove(item.entity);
                 });
                 
                 // 清空起降场实体引用
                 this.landingFieldEntities = {};
             }
             
             this.status = '已清空所有起降场';
         },
        
                 clearHistoricalTracks() {
             if (confirm('确定要清除历史轨迹吗？飞机位置将保留')) {
                 // 清除轨迹线实体，但保留飞机实体
                 Object.values(this.trackPolylines).forEach(entity => {
                     if (entity) this.viewer.entities.remove(entity);
                 });
                 
                 // 清空轨迹线引用
                 this.trackPolylines = {};
                 
                 // 清空轨迹数据中的历史点，只保留最新的点
                 this.flightTracks.forEach(track => {
                     if (track.points && track.points.length > 0) {
                         // 只保留最后一个点
                         track.points = [track.points[track.points.length - 1]];
                     }
                 });
                 
                 this.status = '已清除历史轨迹，飞机位置保留';
             }
         },
         
         clearAllRoutes() {
             if (confirm('确定要清除所有航线吗？')) {
                 // 清除所有航线实体
                 if (this.routeEntities) {
                     Object.values(this.routeEntities).forEach(entity => {
                         if (entity) this.viewer.entities.remove(entity);
                     });
                     
                     // 清空航线实体引用
                     this.routeEntities = {};
                 }
                 
                 this.status = '已清除所有航线';
             }
         },
         
         clearAllLandingFields() {
             if (confirm('确定要清除所有起降场吗？')) {
                 // 清除起降场实体
                 if (this.landingFieldEntities) {
                     Object.values(this.landingFieldEntities).forEach(item => {
                         if (item.entity) this.viewer.entities.remove(item.entity);
                     });
                     
                     // 清空起降场实体引用
                     this.landingFieldEntities = {};
                 }
                 
                 this.status = '已清除所有起降场';
             }
         },
         

         
         // 批量设置方案ID
         setBatchPlanId() {
             if (!this.batchPlanId || this.batchPlanId < 1) {
                 alert('请输入有效的方案ID（大于等于1）');
                 return;
             }
             
             // 为所有记录设置方案ID
             this.geojsonRecords.forEach(record => {
                 record.planId = this.batchPlanId;
             });
             
                              // console.log(`已批量设置 ${this.geojsonRecords.length} 条记录的方案ID为: ${this.batchPlanId}`);
             this.status = `已批量设置方案ID为: ${this.batchPlanId}`;
         },
         
         // 从输入框同步方案ID到批量设置
         updateBatchPlanIdFromInput() {
             const planIdValue = parseInt(this.planId);
             if (!planIdValue || planIdValue < 1) {
                 alert('请输入有效的方案ID（大于等于1）');
                 return;
             }
             
             this.batchPlanId = planIdValue;
             
             // 同时更新所有现有记录的方案ID
             this.geojsonRecords.forEach(record => {
                 record.planId = planIdValue;
             });
             
                              // console.log(`已同步方案ID: ${planIdValue}`);
             this.status = `已同步方案ID为: ${planIdValue}`;
         },
         
         // 重新生成记录名称
         regenerateRecordNames() {
             this.geojsonRecords.forEach((record, index) => {
                 record.name = `${this.batchNamePrefix}${index + 1}`;
             });
                              // console.log('已重新生成记录名称');
         },
         
         // 批量设置记录名称
         setBatchNames() {
             if (!this.batchNamePrefix || this.batchNamePrefix.trim() === '') {
                 alert('请输入有效的名称前缀');
                 return;
             }
             
             const prefix = this.batchNamePrefix.trim();
             
             // 为所有记录设置名称
             this.geojsonRecords.forEach((record, index) => {
                 record.name = `${prefix}${index + 1}`;
             });
             
                              // console.log(`已批量设置 ${this.geojsonRecords.length} 条记录的名称前缀为: ${prefix}`);
             this.status = `已批量设置名称前缀为: ${prefix}`;
         },
        
        updateRenderDelay() {
            // 更新渲染间隔
            if (this.renderInterval) {
                clearInterval(this.renderInterval);
            }
            if (this.enableRealTimeUpdate) {
                this.renderInterval = setInterval(() => {
                    this.renderNewPoints();
                }, this.renderDelay);
            }
        },
        
                 toggleRealTimeUpdate() {
             if (this.enableRealTimeUpdate) {
                 // 启用实时更新
                 this.updateRenderDelay();
             } else {
                 // 禁用实时更新
                 if (this.renderInterval) {
                     clearInterval(this.renderInterval);
                     this.renderInterval = null;
                 }
             }
         },
         
                  // 切换相机锁定
         toggleCameraLock() {
             if (this.cameraLocked) {
                 // 强制锁定当前相机位置
                 this.forceCameraLock = true;
                 this.lastCameraPosition = {
                     destination: this.viewer.camera.position.clone(),
                     orientation: {
                         heading: this.viewer.camera.heading,
                         pitch: this.viewer.camera.pitch,
                         roll: this.viewer.camera.roll
                     }
                 };
                 this.status = '相机位置已强制锁定，地图级别将完全保持稳定';
             } else {
                 // 解锁相机位置
                 this.forceCameraLock = false;
                 this.status = '相机位置已解锁，可以自由移动';
                 
                 // 恢复鼠标滚轮缩放功能
                 this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.WHEEL);
             }
         },
         
         // 锁定当前地图级别
         lockCurrentZoomLevel() {
             this.forceCameraLock = true;
             this.lastCameraPosition = {
                 destination: this.viewer.camera.position.clone(),
                 orientation: {
                     heading: this.viewer.camera.heading,
                     pitch: this.viewer.camera.pitch,
                     roll: this.viewer.camera.roll
                 }
             };
             this.status = `已强制锁定当前地图级别 (${this.currentZoomLevelDisplay}级)，地图将完全保持稳定`;
         },
         
         // 解锁相机
         unlockCamera() {
             this.forceCameraLock = false;
             this.cameraLocked = false;
             this.status = '相机已解锁，可以自由移动和缩放';
             
             // 恢复鼠标滚轮缩放功能
             this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.WHEEL);
         },
         
         toggleHistoricalTracks() {
            // 更新所有轨迹线的可见性
            Object.keys(this.trackPolylines).forEach(trackId => {
                const polylineEntity = this.trackPolylines[trackId];
                if (polylineEntity) {
                    polylineEntity.show = this.showHistoricalTracks;
                }
            });
            
            // 更新状态信息
            if (this.showHistoricalTracks) {
                this.status = '已显示历史轨迹';
            } else {
                this.status = '已隐藏历史轨迹';
            }
        },
        
                 // 创建飞行器图标
         createColoredDroneIcon(color) {
             // 使用指定的飞行器图片
             return 'http://211.159.175.30:8011/uamtest/image/fly/flane.png';
         },
        
                 // 设置当前轨迹
         setCurrentTrack(trackIndex) {
             if (this.isUpdatingSelection) return; // 防止循环调用
             
             this.isUpdatingSelection = true;
             this.currentTrackIndex = trackIndex;
             if (this.flightTracks[trackIndex]) {
                 this.flightPath = this.flightTracks[trackIndex].points;
                 // 同步更新右边面板的选择
                 this.selectedTrackId = this.flightTracks[trackIndex].id;
                 this.onTrackSelectionChange();
                 
                 // 初始化时间轴
                 this.initializeTimeline();
                 
                 this.status = `已选择轨迹${trackIndex + 1}，可进行播放控制`;
             }
             this.isUpdatingSelection = false;
         },
         
         // ================= 时间轴控制 =================
         initializeTimeline() {
             if (!this.hasValidTrack) return;
             
             const track = this.flightTracks[this.currentTrackIndex];
             if (track.points && track.points.length > 0) {
                 // 计算总时长
                 const lastPoint = track.points[track.points.length - 1];
                 this.totalDuration = lastPoint.timestamp;
                 this.currentTime = 0;
                 this.currentTimePercent = 0;
                 
                 // 停止当前播放
                 this.stopPlayback();
                 
                 // 应用时间播放方案
                 this.applyTimeMode();
             }
         },
         
         playPause() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.shouldAnimate = !this.viewer.clock.shouldAnimate;
                     this.playing = this.viewer.clock.shouldAnimate;
                     
                     // 更新状态
                     this.status = this.playing ? 'Cesium原生时间播放已启动' : 'Cesium原生时间播放已暂停';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 if (this.playing) {
                     this.stopPlayback();
                 } else {
                     this.startPlayback();
                 }
                 
                 // 同时控制Cesium内置时钟
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.shouldAnimate = this.playing;
                 }
             }
         },
         
         stepForward() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 10, new Cesium.JulianDate());
                     if (Cesium.JulianDate.compare(newTime, this.viewer.clock.stopTime) <= 0) {
                         this.viewer.clock.currentTime = newTime;
                     }
                     this.status = 'Cesium原生时间播放：向前10秒';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime += 10;
                 if (this.currentTime > this.totalDuration) {
                     this.currentTime = this.totalDuration;
                 }
                 this.currentTimePercent = (this.currentTime / this.totalDuration) * 100;
                 this.updateAircraftPositionForTime();
                 this.status = '自定义时间播放：向前10秒';
             }
         },
         
         stepBackward() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, -10, new Cesium.JulianDate());
                     if (Cesium.JulianDate.compare(newTime, this.viewer.clock.startTime) >= 0) {
                         this.viewer.clock.currentTime = newTime;
                     }
                     this.status = 'Cesium原生时间播放：向后10秒';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime -= 10;
                 if (this.currentTime < 0) {
                     this.currentTime = 0;
                 }
                 this.currentTimePercent = (this.currentTime / this.totalDuration) * 100;
                 this.updateAircraftPositionForTime();
                 this.status = '自定义时间播放：向后10秒';
             }
         },
         
         resetTime() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.currentTime = this.viewer.clock.startTime.clone();
                     this.status = 'Cesium原生时间播放：已重置到开始时间';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime = 0;
                 this.currentTimePercent = 0;
                 this.updateAircraftPositionForTime();
                 this.status = '自定义时间播放：已重置到开始时间';
             }
         },
         
                  startPlayback() {
             if (!this.hasValidTrack) return;
             
             this.playing = true;
             this.playbackStartTime = Date.now();
             
             // 启动Cesium内置时钟
             if (this.viewer && this.viewer.clock) {
                 this.viewer.clock.shouldAnimate = true;
                 this.viewer.clock.multiplier = this.playbackSpeed;
             }
             
             // 使用setInterval，但频率更高，确保平滑
             this.playbackInterval = setInterval(() => {
                 if (!this.playing) return;
                 
                 const now = Date.now();
                 const elapsedTime = (now - this.playbackStartTime) / 1000;
                 
                 // 计算播放进度
                 this.currentTime = (elapsedTime * this.playbackSpeed);
                 
                 if (this.currentTime >= this.totalDuration) {
                     this.currentTime = this.totalDuration;
                     this.stopPlayback();
                     return;
                 }
                 
                 this.currentTimePercent = (this.currentTime / this.totalDuration) * 100;
                 this.updateAircraftPositionForTime();
                 
                 // 调试信息：每2秒输出一次
                 if (Math.floor(this.currentTime) % 2 === 0 && this.currentTime > 0) {
                     // console.log(`播放时间: ${this.currentTime.toFixed(1)}s, 进度: ${this.currentTimePercent.toFixed(1)}%`);
                 }
                 
             }, 50); // 20FPS，平衡性能和流畅度
         },
         
         stopPlayback() {
             this.playing = false;
             if (this.playbackInterval) {
                 clearInterval(this.playbackInterval);
                 this.playbackInterval = null;
             }
             // 重置播放开始时间
             this.playbackStartTime = null;
             
             // 停止Cesium内置时钟
             if (this.viewer && this.viewer.clock) {
                 this.viewer.clock.shouldAnimate = false;
             }
         },
         
         stepForward() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     // 暂停播放，避免拖动时的跳动
                     const wasPlaying = this.viewer.clock.shouldAnimate;
                     this.viewer.clock.shouldAnimate = false;
                     
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, 10, new Cesium.JulianDate());
                     // 确保不超过结束时间
                     if (Cesium.JulianDate.compare(newTime, this.viewer.clock.stopTime) <= 0) {
                         this.viewer.clock.currentTime = newTime;
                     } else {
                         this.viewer.clock.currentTime = this.viewer.clock.stopTime.clone();
                     }
                     
                     // 恢复播放状态
                     this.viewer.clock.shouldAnimate = wasPlaying;
                     this.playing = wasPlaying;
                     
                     this.status = 'Cesium原生时间播放：向前10秒';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime += 10; // 向前10秒
                 if (this.currentTime > this.totalDuration) {
                     this.currentTime = this.totalDuration;
                 }
                 this.currentTimePercent = (this.currentTime / this.totalDuration) * 100;
                 this.updateAircraftPositionForTime();
                 
                 // 同时控制Cesium内置时钟
                 if (this.viewer && this.viewer.clock) {
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.startTime, this.currentTime, new Cesium.JulianDate());
                     this.viewer.clock.currentTime = newTime;
                 }
             }
         },
         
         stepBackward() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     // 暂停播放，避免拖动时的跳动
                     const wasPlaying = this.viewer.clock.shouldAnimate;
                     this.viewer.clock.shouldAnimate = false;
                     
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.currentTime, -10, new Cesium.JulianDate());
                     // 确保不超过开始时间
                     if (Cesium.JulianDate.compare(newTime, this.viewer.clock.startTime) >= 0) {
                         this.viewer.clock.currentTime = newTime;
                     } else {
                         this.viewer.clock.currentTime = this.viewer.clock.startTime.clone();
                     }
                     
                     // 恢复播放状态
                     this.viewer.clock.shouldAnimate = wasPlaying;
                     this.playing = wasPlaying;
                     
                     this.status = 'Cesium原生时间播放：向后10秒';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime -= 10; // 向后10秒
                 if (this.currentTime < 0) {
                     this.currentTime = 0;
                 }
                 this.currentTimePercent = (this.currentTime / this.totalDuration) * 100;
                 this.updateAircraftPositionForTime();
                 
                 // 同时控制Cesium时钟
                 if (this.viewer && this.viewer.clock) {
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.startTime, this.currentTime, new Cesium.JulianDate());
                     this.viewer.clock.currentTime = newTime;
                 }
             }
         },
         
         resetTime() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     // 暂停播放，避免拖动时的跳动
                     const wasPlaying = this.viewer.clock.shouldAnimate;
                     this.viewer.clock.shouldAnimate = false;
                     
                     this.viewer.clock.currentTime = this.viewer.clock.startTime.clone();
                     
                     // 恢复播放状态
                     this.viewer.clock.shouldAnimate = wasPlaying;
                     this.playing = wasPlaying;
                     
                     this.status = 'Cesium原生时间播放：已重置到开始时间';
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime = 0;
                 this.currentTimePercent = 0;
                 this.updateAircraftPositionForTime();
                 
                 // 同时控制Cesium内置时钟
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.currentTime = this.viewer.clock.startTime.clone();
                 }
             }
         },
         
         seekToTime() {
             if (!this.hasValidTrack) return;
             
             // 防抖处理，避免频繁更新
             if (this.seekDebounceTimer) {
                 clearTimeout(this.seekDebounceTimer);
             }
             
             this.seekDebounceTimer = setTimeout(() => {
                 this.performSeek();
             }, 50); // 50ms防抖
         },
         
         performSeek() {
             if (!this.hasValidTrack) return;
             
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 if (this.viewer && this.viewer.clock) {
                     // 暂停播放，避免拖动时的跳动
                     const wasPlaying = this.viewer.clock.shouldAnimate;
                     this.viewer.clock.shouldAnimate = false;
                     
                     const totalSeconds = Cesium.JulianDate.secondsDifference(this.viewer.clock.stopTime, this.viewer.clock.startTime);
                     const targetSeconds = (this.currentTimePercent / 100) * totalSeconds;
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.startTime, targetSeconds, new Cesium.JulianDate());
                     this.viewer.clock.currentTime = newTime;
                     
                     // 恢复播放状态
                     this.viewer.clock.shouldAnimate = wasPlaying;
                     this.playing = wasPlaying;
                 }
             } else {
                 // 方案A：使用自定义时间播放
                 this.currentTime = (this.currentTimePercent / 100) * this.totalDuration;
                 
                 // 重置播放开始时间，确保从新位置开始播放
                 if (this.playing) {
                     this.playbackStartTime = Date.now() - (this.currentTime / this.playbackSpeed) * 1000;
                 }
                 
                 // 同步Cesium内置时钟时间
                 if (this.viewer && this.viewer.clock) {
                     const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.startTime, this.currentTime, new Cesium.JulianDate());
                     this.viewer.clock.currentTime = newTime;
                 }
                 
                 this.updateAircraftPositionForTime();
             }
         },
         
         updatePlaybackSpeed() {
             if (this.timeMode === 'cesium') {
                 // 方案B：更新Cesium内置时钟的播放速度
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.multiplier = this.playbackSpeed;
                 }
             } else {
                 // 方案A：如果使用自定义播放，需要重新计算播放开始时间
                 if (this.playing) {
                     this.playbackStartTime = Date.now() - (this.currentTime / this.playbackSpeed) * 1000;
                 }
             }
         },
         
         applyTimeMode() {
             if (this.timeMode === 'cesium') {
                 // 方案B：使用Cesium内置时间播放
                 this.stopPlayback(); // 停止自定义播放
                 
                 // 重新创建带时间属性的轨迹实体
                 this.recreateTracksWithTimeProperties();
                 
                 // 配置Cesium时钟
                 if (this.viewer && this.viewer.clock) {
                     // 计算所有轨迹的时间范围
                     let globalMinTimestamp = Infinity;
                     let globalMaxTimestamp = -Infinity;
                     
                     this.flightTracks.forEach(track => {
                         if (track.points && track.points.length > 0) {
                             const timestamps = track.points.map(p => p.timestamp_absolute || p.ts || p.timestamp).filter(t => t !== undefined);
                             if (timestamps.length > 0) {
                                 const minTimestamp = Math.min(...timestamps);
                                 const maxTimestamp = Math.max(...timestamps);
                                 globalMinTimestamp = Math.min(globalMinTimestamp, minTimestamp);
                                 globalMaxTimestamp = Math.max(globalMaxTimestamp, maxTimestamp);
                             }
                         }
                     });
                     
                     // 如果没有有效的时间戳，使用默认时间范围
                     if (globalMinTimestamp === Infinity || globalMaxTimestamp === -Infinity) {
                         const startTime = Cesium.JulianDate.fromDate(new Date('2025-08-30T16:00:00Z'));
                         const stopTime = Cesium.JulianDate.fromDate(new Date('2025-08-31T14:00:00Z'));
                         
                         this.viewer.clock.startTime = startTime;
                         this.viewer.clock.stopTime = stopTime;
                         this.viewer.clock.currentTime = startTime;
                     } else {
                         // 使用实际的时间范围
                         const startTime = Cesium.JulianDate.fromDate(new Date(globalMinTimestamp));
                         const stopTime = Cesium.JulianDate.fromDate(new Date(globalMaxTimestamp));
                         
                         this.viewer.clock.startTime = startTime;
                         this.viewer.clock.stopTime = stopTime;
                         this.viewer.clock.currentTime = startTime;
                         
                         // 设置时间轴范围
                         this.viewer.timeline.zoomTo(startTime, stopTime);
                     }
                     
                     this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
                     this.viewer.clock.multiplier = this.playbackSpeed;
                     this.viewer.clock.shouldAnimate = true; // 自动开始播放
                     this.playing = true; // 更新播放状态
                 }
                 
                 this.status = '已切换到Cesium内置时间播放模式，自动开始播放';
             } else {
                 // 方案A：使用自定义时间播放
                 if (this.viewer && this.viewer.clock) {
                     this.viewer.clock.shouldAnimate = false; // 停止Cesium时钟
                 }
                 
                 this.status = '已切换到自定义时间播放模式';
             }
         },
         
         recreateTracksWithTimeProperties() {
             // 清除现有的轨迹实体
             this.clearAllTracks();
             
             // 重新创建带时间属性的轨迹
             this.flightTracks.forEach(track => {
                 if (track.points && track.points.length > 0) {
                     this.createTrackWithTimeProperties(track);
                 }
             });
         },
         
         createTrackWithTimeProperties(track) {
             if (!track.points || track.points.length === 0) return;
             
             // 创建时间点数组
             const timePoints = [];
             const positions = [];
             
             // 找到轨迹的时间范围
             const timestamps = track.points.map(p => p.timestamp_absolute || p.ts || p.timestamp).filter(t => t !== undefined);
             if (timestamps.length === 0) {
                 console.warn('轨迹没有有效的时间戳:', track.id);
                 return;
             }
             
             const minTimestamp = Math.min(...timestamps);
             const maxTimestamp = Math.max(...timestamps);
             
             track.points.forEach((point, index) => {
                 // 使用实际的时间戳
                 const timestamp = point.timestamp_absolute || point.ts || point.timestamp;
                 if (timestamp !== undefined) {
                     const time = Cesium.JulianDate.fromDate(new Date(timestamp));
                     timePoints.push(time);
                     positions.push(Cesium.Cartesian3.fromDegrees(
                         point.longitude, 
                         point.latitude, 
                         point.altitude || 0
                     ));
                 }
             });
             
             // 创建带时间属性的轨迹线
             const trackEntity = this.viewer.entities.add({
                 id: `track-${track.id}`,
                 name: track && track.id ? `轨迹${track.id}` : '未知轨迹',
                 path: {
                     positions: positions,
                     material: Cesium.Color.CYAN.withAlpha(0.8),
                     width: 3,
                     show: true,
                     leadTime: 0,
                     trailTime: 0,
                     // 关键：设置时间属性
                     time: timePoints
                 }
             });
             
             // 创建带时间属性的飞机实体
             const aircraftEntity = this.viewer.entities.add({
                 id: `aircraft-${track.id}`,
                 name: track && track.id ? `轨迹${track.id}` : '未知轨迹',
                 position: positions[0],
                 model: {
                     uri: 'https://raw.githubusercontent.com/AnalyticalGraphicsInc/cesium/master/Apps/SampleData/models/CesiumAir/Cesium_Air.glb',
                     minimumPixelSize: 64,
                     maximumScale: 20000,
                     scale: 1.0
                 },
                 label: {
                     text: track && track.id ? `轨迹${track.id}` : '未知轨迹',
                     font: '14pt monospace',
                     style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                     outlineWidth: 2,
                     verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                     pixelOffset: new Cesium.Cartesian2(0, -9),
                     show: true
                 },
                 // 关键：设置时间属性
                 availability: new Cesium.TimeIntervalCollection([
                     new Cesium.TimeInterval({
                         start: timePoints[0],
                         stop: timePoints[timePoints.length - 1]
                     })
                 ]),
                 // 设置方向控制，让飞机朝向飞行方向
                 orientation: new Cesium.VelocityOrientationProperty(positions)
             });
             
             // 存储实体引用
             this.trackEntities[track.id] = trackEntity;
             this.aircraftEntities[track.id] = aircraftEntity;
         },
         

         
         updateAircraftPositionForTime() {
             if (!this.hasValidTrack) return;
             
             // 方案B不需要手动更新飞机位置，Cesium会自动处理
             if (this.timeMode === 'cesium') {
                 return;
             }
             
             const track = this.flightTracks[this.currentTrackIndex];
             // 直接使用当前时间（秒），不需要转换为毫秒
             const targetTime = this.currentTime;
              
              // 找到当前时间对应的点
              const currentPoint = this.getCurrentPoint(track, targetTime);
              
              // 同步Cesium内置时钟时间
              if (this.viewer && this.viewer.clock) {
                  const newTime = Cesium.JulianDate.addSeconds(this.viewer.clock.startTime, this.currentTime, new Cesium.JulianDate());
                  this.viewer.clock.currentTime = newTime;
              }
              
              if (currentPoint) {
                  // 更新飞机位置
                  const aircraftEntity = this.aircraftEntities[track.id];
                  if (aircraftEntity) {
                      try {
                          // 直接设置飞机位置，不使用平滑插值，确保匀速移动
                          aircraftEntity.position = Cesium.Cartesian3.fromDegrees(
                              currentPoint.longitude,
                              currentPoint.latitude,
                              currentPoint.altitude
                          );
                          
                          // 计算并更新飞行方向
                          const heading = this.calculateAircraftHeading(track, currentPoint, targetTime);
                          if (heading !== null) {
                              const headingRadians = Cesium.Math.toRadians(heading);
                              // 检查实体类型，避免设置不存在的属性
                              if (aircraftEntity.billboard) {
                                  aircraftEntity.billboard.rotation = headingRadians;
                              }
                              
                              // 更新飞行方向显示
                              const direction = this.getHeadingDirection(heading);
                              this.headingText = `${heading.toFixed(1)}° (${direction})`;
                          } else {
                              this.headingText = '-';
                          }
                          
                          // 移除标签更新，性能优先
                      } catch (e) {
                          console.warn('更新飞机位置失败:', currentPoint, e);
                      }
                  }
                  
                  // 更新轨迹线颜色（时间轴模式）
                  this.updateTrackPolylineColor(track.id, track, targetTime);
                  
                  // 更新位置信息显示
                  const trackName = track.aircraft_type || `轨迹${this.currentTrackIndex + 1}`;
                  const batteryInfo = currentPoint.battery !== undefined ? ` - 电池: ${Math.round(currentPoint.battery * 100)}%` : '';
                  
                  this.posText = `${trackName}: ${currentPoint.longitude.toFixed(4)}, ${currentPoint.latitude.toFixed(4)}`;
                  this.segText = `时间轴位置 - 高度: ${currentPoint.altitude}m${batteryInfo}`;
              }
          },

         onTick() {
             if (this.timeMode === 'cesium') {
                 // 方案B：Cesium内置时间播放，不需要手动更新
                 return;
             }
             
             // 方案A：只有在非播放模式下才显示实时位置
             if (!this.playing && this.flightPath && this.flightPath.length > 0) {
                 const currentTime = Date.now();
                 const track = this.flightTracks[this.currentTrackIndex];
                 const relativeTime = (currentTime - track.startTime) / 1000;
                 const currentPoint = this.getCurrentPoint(track, relativeTime);
                 
                 if (currentPoint) {
                     const track = this.flightTracks[this.currentTrackIndex];
                     const trackName = track.aircraft_type || `轨迹${this.currentTrackIndex + 1}`;
                     const batteryInfo = currentPoint.battery !== undefined ? ` - 电池: ${Math.round(currentPoint.battery * 100)}%` : '';
                     
                     this.posText = `${trackName}: ${currentPoint.longitude.toFixed(4)}, ${currentPoint.latitude.toFixed(4)}`;
                     this.segText = `实时位置 - 高度: ${currentPoint.altitude}m${batteryInfo}`;
                 }
             }
         },

         
         // ================= 多边形绘制 =================
         startDrawPolygon() {
             if (this.drawing) return;
             this.drawing = true;
             this.drawPositions = [];
             
             // 临时禁用相机锁定，允许绘制时自由移动
             const wasCameraLocked = this.forceCameraLock;
             this.forceCameraLock = false;
             
             if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
             if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
             if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
             this.drawHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);
             
             // 保存绘制前的相机锁定状态
             this._preDrawCameraLocked = wasCameraLocked;
             
             // 临时移除相机变化监听器，避免绘制时被干扰
             if (this.cameraChangeListener) {
                 this.viewer.camera.changed.removeEventListener(this.cameraChangeListener);
             }

             // 左键点击：落点
             this.drawHandler.setInputAction((movement) => {
                 const cart = this.getCartesianFromMouse(movement.position);
                 if (!cart) return;
                 this.drawPositions.push(cart);
                 this.ensureDynamicPolygon();
             }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

             // 右键点击：完成绘制
             this.drawHandler.setInputAction((movement) => {
                 if (this.drawing && this.drawPositions.length >= 3) {
                     this.finishDrawPolygon();
                 }
             }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

             // 移动：动态预览末点
             this.drawHandler.setInputAction((movement) => {
                 if (!this.drawing || this.drawPositions.length === 0) return;
                 const cart = this.getCartesianFromMouse(movement.endPosition);
                 if (!cart) return;
                 const temp = this.drawPositions.slice();
                 temp.push(cart);
                 this.updateDynamicPolygon(temp);
             }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
         },
         finishDrawPolygon() {
             if (!this.drawing) return;
             this.drawing = false;
             if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
             
             // 恢复绘制前的相机锁定状态
             if (this._preDrawCameraLocked) {
                 this.forceCameraLock = true;
                 this.status = '绘制完成，相机锁定已恢复';
             }
             
             // 重新添加相机变化监听器
             if (this.cameraChangeListener) {
                 this.viewer.camera.changed.addEventListener(this.cameraChangeListener);
             }
             
             // 最终以 drawPositions 生成实体
             if (this.drawPositions.length < 3) return;
             this.updateDynamicPolygon(this.drawPositions, true);
         },
         clearDrawPolygon() {
             this.drawing = false;
             this.drawPositions = [];
             this.polygonGeoJSON = null; // 清除GeoJSON
             
             // 恢复绘制前的相机锁定状态
             if (this._preDrawCameraLocked) {
                 this.forceCameraLock = true;
                 this.status = '绘制已清空，相机锁定已恢复';
             }
             
             // 重新添加相机变化监听器
             if (this.cameraChangeListener) {
                 this.viewer.camera.changed.addEventListener(this.cameraChangeListener);
             }
             
             // 清除所有记录及其对应的实体
             for (const record of this.geojsonRecords) {
                 if (record.polygonEntity) {
                     this.viewer.entities.remove(record.polygonEntity);
                 }
                 if (record.outlineEntity) {
                     this.viewer.entities.remove(record.outlineEntity);
                 }
             }
             this.geojsonRecords = []; // 清空记录数组
             
             if (this.drawHandler) { this.drawHandler.destroy(); this.drawHandler = null; }
             if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
             if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
         },
         getCartesianFromMouse(winPos) {
             if (!winPos) return null;
             const scene = this.viewer.scene;
             let cartesian = null;
             if (scene.pickPositionSupported) {
                 cartesian = scene.pickPosition(winPos);
             }
             if (!Cesium.defined(cartesian)) {
                 const ray = this.viewer.camera.getPickRay(winPos);
                 cartesian = scene.globe.pick(ray, scene);
             }
             return cartesian || null;
         },
         ensureDynamicPolygon() {
             if (this.drawPolygonEntity) return;
             const hierarchyCb = new Cesium.CallbackProperty(() => {
                 const list = (this._previewPositions || this.drawPositions);
                 if (!list || list.length < 3) return null;
                 return new Cesium.PolygonHierarchy(list);
             }, false);
             this.drawPolygonEntity = this.viewer.entities.add({
                 polygon: {
                     hierarchy: hierarchyCb,
                     material: Cesium.Color.fromBytes(255, 165, 0, 180), // 更明显的橙色，增加透明度
                     perPositionHeight: false, // 修复空洞问题，不使用高度
                     outline: true,
                     outlineColor: Cesium.Color.ORANGE,
                     outlineWidth: 3
                 }
             });
             this.drawOutlineEntity = this.viewer.entities.add({
                 polyline: {
                     positions: new Cesium.CallbackProperty(() => {
                         const list = (this._previewPositions || this.drawPositions);
                         if (!list || list.length < 2) return [];
                         return list.concat(list[0]); // 闭合预览
                     }, false),
                     width: 2,
                     material: Cesium.Color.ORANGE
                 }
             });
         },
         updateDynamicPolygon(positions, finalize = false) {
             this._previewPositions = positions;
             if (finalize) {
                 // 清除预览实体
                 if (this.drawPolygonEntity) { this.viewer.entities.remove(this.drawPolygonEntity); this.drawPolygonEntity = null; }
                 if (this.drawOutlineEntity) { this.viewer.entities.remove(this.drawOutlineEntity); this.drawOutlineEntity = null; }
                 this._previewPositions = null;
                 
                 // 生成GeoJSON（会自动创建实体并添加到记录中）
                 this.generateGeoJSON(positions);
             }
         },
         
         // 生成GeoJSON
         generateGeoJSON(positions) {
             if (!positions || positions.length < 3) {
                 this.polygonGeoJSON = null;
                 return;
             }
             
             // 将Cartesian3坐标转换为经纬度
             const coordinates = [];
             for (const pos of positions) {
                 const cartographic = Cesium.Cartographic.fromCartesian(pos);
                 const longitude = Cesium.Math.toDegrees(cartographic.longitude);
                 const latitude = Cesium.Math.toDegrees(cartographic.latitude);
                 coordinates.push([longitude, latitude]);
             }
             
             // 闭合多边形（首尾相连）
             if (coordinates.length > 0) {
                 coordinates.push(coordinates[0]);
             }
             
             const geojson = {
                 type: "Feature",
                 properties: {
                     name: "绘制多边形",
                     timestamp: new Date().toISOString()
                 },
                 geometry: {
                     type: "Polygon",
                     coordinates: [coordinates]
                 }
             };
             
             this.polygonGeoJSON = JSON.stringify(geojson, null, 2);
             
             // 添加到记录表格
             this.geojsonRecords.push({
                 timestamp: new Date(),
                 pointCount: positions.length,
                 name: `${this.batchNamePrefix}${this.geojsonRecords.length + 1}`, // 自动生成名称
                 planId: this.planId || 1, // 使用从轨迹获取的方案ID，默认为1
                 geojson: geojson,
                 geojsonString: this.polygonGeoJSON,
                 polygonEntity: null, // 将在下面设置
                 outlineEntity: null,  // 将在下面设置
                 selectedDispatchOption: null // 选中的导调选项
             });
             
             // 获取刚添加的记录索引
             const recordIndex = this.geojsonRecords.length - 1;
             
             // 创建多边形实体并保存引用
             const polygonEntity = this.viewer.entities.add({
                 polygon: {
                     hierarchy: new Cesium.PolygonHierarchy(positions),
                     material: Cesium.Color.fromBytes(255, 165, 0, 180), // 更明显的橙色
                     perPositionHeight: false, // 修复空洞问题，不使用高度
                     outline: true,
                     outlineColor: Cesium.Color.ORANGE,
                     outlineWidth: 3
                 }
             });
             
             const outlineEntity = this.viewer.entities.add({
                 polyline: {
                     positions: positions.concat(positions[0]),
                     width: 2,
                     material: Cesium.Color.ORANGE
                 }
             });
             
             // 保存实体引用到记录中
             this.geojsonRecords[recordIndex].polygonEntity = polygonEntity;
             this.geojsonRecords[recordIndex].outlineEntity = outlineEntity;
         },
         
         // 复制GeoJSON到剪贴板
         copyGeoJSON() {
             if (!this.polygonGeoJSON) return;
             
             navigator.clipboard.writeText(this.polygonGeoJSON).then(() => {
                 // 临时显示复制成功提示
                 const btn = event.target;
                 const originalText = btn.textContent;
                 btn.textContent = '已复制';
                 btn.style.background = '#4CAF50';
                 setTimeout(() => {
                     btn.textContent = originalText;
                     btn.style.background = '#2196F3';
                 }, 1000);
             }).catch(err => {
                 console.error('复制失败:', err);
                 // 降级方案：使用传统方法
                 const textArea = document.createElement('textarea');
                 textArea.value = this.polygonGeoJSON;
                 document.body.appendChild(textArea);
                 textArea.select();
                 document.execCommand('copy');
                 document.body.removeChild(textArea);
                 
                 const btn = event.target;
                 const originalText = btn.textContent;
                 btn.textContent = '已复制';
                 btn.style.background = '#4CAF50';
                 setTimeout(() => {
                     btn.textContent = originalText;
                     btn.style.background = '#2196F3';
                 }, 1000);
             });
         },
         
         // 格式化时间显示
         formatTime(date) {
             if (!date) return '-';
             
             // 如果是数字，检查是否是秒级时间戳
             if (typeof date === 'number') {
                 // 如果小于10000000000，说明是秒级时间戳，需要转换为毫秒
                 if (date < 10000000000) {
                     const milliseconds = date * 1000;
                     const d = new Date(milliseconds);
                     const result = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
                     return result;
                 } else {
                     // 毫秒级时间戳，直接转换
                     const d = new Date(date);
                     const result = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
                     return result;
                 }
             }
             
             // 如果是字符串，尝试解析
             if (typeof date === 'string') {
                 // 如果是纯数字字符串，可能是秒级时间戳
                 if (/^\d{10}$/.test(date)) {
                     const milliseconds = parseInt(date) * 1000;
                     const d = new Date(milliseconds);
                     const result = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
                     return result;
                 }
                 
                 // 尝试直接解析字符串
                 const d = new Date(date);
                 if (!isNaN(d.getTime())) {
                     const result = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
                     return result;
                 }
             }
             
             // 其他情况直接显示原始值
             return String(date);
         },
         
         // 复制记录中的GeoJSON
         copyRecordGeoJSON(index) {
             const record = this.geojsonRecords[index];
             if (!record) return;
             
             navigator.clipboard.writeText(record.geojsonString).then(() => {
                 // 临时显示复制成功提示
                 const btn = event.target;
                 const originalText = btn.textContent;
                 btn.textContent = '已复制';
                 btn.style.background = '#4CAF50';
                 setTimeout(() => {
                     btn.textContent = originalText;
                     btn.style.background = '#2196F3';
                 }, 1000);
             }).catch(err => {
                 console.error('复制失败:', err);
                 // 降级方案
                 const textArea = document.createElement('textarea');
                 textArea.value = record.geojsonString;
                 document.body.appendChild(textArea);
                 textArea.select();
                 document.execCommand('copy');
                 document.body.removeChild(textArea);
                 
                 const btn = event.target;
                 const originalText = btn.textContent;
                 btn.textContent = '已复制';
                 btn.style.background = '#4CAF50';
                 setTimeout(() => {
                     btn.textContent = originalText;
                     btn.style.background = '#2196F3';
                 }, 1000);
             });
         },
         
         // 查看记录中的完整GeoJSON
         viewRecordGeoJSON(index) {
             const record = this.geojsonRecords[index];
             if (!record) return;
             
             // 显示在弹窗中
             alert(`GeoJSON记录 ${index + 1}:\n\n${record.geojsonString}`);
         },
         
         // 删除记录
         deleteRecord(index) {
             if (confirm(`确定要删除第 ${index + 1} 条记录吗？`)) {
                 const record = this.geojsonRecords[index];
                 if (record) {
                     // 删除对应的多边形实体
                     if (record.polygonEntity) {
                         this.viewer.entities.remove(record.polygonEntity);
                     }
                     if (record.outlineEntity) {
                         this.viewer.entities.remove(record.outlineEntity);
                     }
                 }
                 // 从数组中删除记录
                 this.geojsonRecords.splice(index, 1);
                 
                 // 重新生成剩余记录的名称
                 this.regenerateRecordNames();
             }
         },
         
         // 发送局部避障消息
         sendLocalAvoidance(record) {
             // 调用统一的导调消息发送方法
             this.sendDispatchMessage(2, record);
         },
         
         // 获取导调类型名称
         getDispatchTypeName(wsClientType) {
             const typeMap = {
                 '2': '局部避障',
                 '7': '返航',
                 '8': '迫降',
                 '9': '坠毁'
             };
             return typeMap[wsClientType] || `未知类型(${wsClientType})`;
         },
         
         // 发送返航消息
         sendReturnHome(record) {
             // 调用统一的导调消息发送方法
             this.sendDispatchMessage(7, record);
         },
         
         // 发送迫降消息
         sendForcedLanding(record) {
             // 调用统一的导调消息发送方法
             this.sendDispatchMessage(8, record);
         },
         
         // 发送坠毁消息
         sendCrash(record) {
             // 调用统一的导调消息发送方法
             this.sendDispatchMessage(9, record);
         },
         
         // 格式化播放时间显示（秒数转HH:mm:ss）
         formatPlayTime(seconds) {
             const hours = Math.floor(seconds / 3600);
             const minutes = Math.floor((seconds % 3600) / 60);
             const secs = Math.floor(seconds % 60);
             return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
         },
         
         // 轨迹选择变化处理
         onTrackSelectionChange() {
             if (this.isUpdatingSelection) return; // 防止循环调用
             
             if (this.selectedTrackId) {
                 // 查找选中的轨迹数据
                 this.selectedTrackData = this.flightTracks.find(track => track.id === this.selectedTrackId);
                 
                 // 同步更新左边面板的选择
                 const trackIndex = this.flightTracks.findIndex(track => track.id === this.selectedTrackId);
                 if (trackIndex !== -1) {
                     this.isUpdatingSelection = true;
                     this.currentTrackIndex = trackIndex;
                     this.currentTrack = this.selectedTrackData;
                     this.flightPath = this.selectedTrackData.points;
                     this.initializeTimeline();
                     this.isUpdatingSelection = false;
                     
                     // 自动定位到选中的任务
                     this.focusToSelectedTask();
                 }
                 
                 // 更新选中的任务信息
                 this.updateSelectedTaskInfo(this.selectedTrackId);
             } else {
                 this.selectedTrackData = null;
                 this.selectedTaskInfo = null;
             }
         },
         
         // 定位到选中的任务
         focusToSelectedTask() {
             if (!this.selectedTrackData || !this.selectedTrackData.points || this.selectedTrackData.points.length === 0) {
                 console.warn('选中的轨迹没有有效的轨迹点数据');
                 return;
             }
             
             const firstPoint = this.selectedTrackData.points[0];
             
             // 验证坐标的有效性
             if (firstPoint && 
                 typeof firstPoint.longitude === 'number' && !isNaN(firstPoint.longitude) &&
                 typeof firstPoint.latitude === 'number' && !isNaN(firstPoint.latitude) &&
                 firstPoint.longitude >= -180 && firstPoint.longitude <= 180 &&
                 firstPoint.latitude >= -90 && firstPoint.latitude <= 90) {
                 
                 const height = Math.max(30000, (firstPoint.altitude || 0) + 80000);
                 
                 try {
                     this.viewer.camera.setView({
                         destination: Cesium.Cartesian3.fromDegrees(firstPoint.longitude, firstPoint.latitude, height),
                         orientation: { heading: 0.0, pitch: -Cesium.Math.PI_OVER_TWO + 0.2, roll: 0.0 }
                     });
                     
                     // 更新状态
                     const taskName = this.getTaskNameByTrackId(this.selectedTrackId) || '未知任务';
                     this.status = `已定位到任务: ${taskName} (${firstPoint.longitude.toFixed(4)}, ${firstPoint.latitude.toFixed(4)})`;
                     console.log(`已自动定位到任务: ${taskName}`, firstPoint);
                 } catch (e) {
                     console.error('定位到选中任务失败:', e);
                     this.status = '定位到选中任务失败';
                 }
             } else {
                 console.warn('选中任务的第一个轨迹点坐标无效:', firstPoint);
             }
         }
    }
}).mount('#app');
</script>
</body>
</html>
    
    